tizen 2.4 release accepted/tizen_2.4_mobile tizen_2.4 accepted/tizen/2.4/mobile/20151029.040702 submit/tizen_2.4/20151028.062842 tizen_2.4_mobile_release
authorjk7744.park <jk7744.park@samsung.com>
Sat, 24 Oct 2015 06:50:44 +0000 (15:50 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sat, 24 Oct 2015 06:50:44 +0000 (15:50 +0900)
97 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
COPYING.LIB [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Examples/ckbook.b [new file with mode: 0644]
Examples/pi.b [new file with mode: 0644]
Examples/primes.b [new file with mode: 0644]
Examples/twins.b [new file with mode: 0644]
FAQ [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
Test/BUG.bc [new file with mode: 0644]
Test/array.b [new file with mode: 0644]
Test/arrayp.b [new file with mode: 0644]
Test/aryprm.b [new file with mode: 0644]
Test/atan.b [new file with mode: 0644]
Test/checklib.b [new file with mode: 0644]
Test/div.b [new file with mode: 0644]
Test/exp.b [new file with mode: 0644]
Test/fact.b [new file with mode: 0644]
Test/jn.b [new file with mode: 0644]
Test/ln.b [new file with mode: 0644]
Test/mul.b [new file with mode: 0644]
Test/raise.b [new file with mode: 0644]
Test/signum [new file with mode: 0644]
Test/sine.b [new file with mode: 0644]
Test/sqrt.b [new file with mode: 0644]
Test/sqrt1.b [new file with mode: 0644]
Test/sqrt2.b [new file with mode: 0644]
Test/testfn.b [new file with mode: 0644]
Test/timetest [new file with mode: 0755]
acconfig.h [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
bc/Makefile.am [new file with mode: 0644]
bc/Makefile.in [new file with mode: 0644]
bc/bc.c [new file with mode: 0644]
bc/bc.h [new file with mode: 0644]
bc/bc.y [new file with mode: 0644]
bc/bcdefs.h [new file with mode: 0644]
bc/const.h [new file with mode: 0644]
bc/execute.c [new file with mode: 0644]
bc/fix-libmath_h [new file with mode: 0755]
bc/global.c [new file with mode: 0644]
bc/global.h [new file with mode: 0644]
bc/libmath.b [new file with mode: 0644]
bc/libmath.h [new file with mode: 0644]
bc/load.c [new file with mode: 0644]
bc/main.c [new file with mode: 0644]
bc/proto.h [new file with mode: 0644]
bc/sbc.y [new file with mode: 0644]
bc/scan.c [new file with mode: 0644]
bc/scan.l [new file with mode: 0644]
bc/storage.c [new file with mode: 0644]
bc/util.c [new file with mode: 0644]
config.h.in [new file with mode: 0644]
configure [new file with mode: 0755]
configure.in [new file with mode: 0644]
dc/Makefile.am [new file with mode: 0644]
dc/Makefile.in [new file with mode: 0644]
dc/array.c [new file with mode: 0644]
dc/dc-proto.h [new file with mode: 0644]
dc/dc-regdef.h [new file with mode: 0644]
dc/dc.c [new file with mode: 0644]
dc/dc.h [new file with mode: 0644]
dc/eval.c [new file with mode: 0644]
dc/misc.c [new file with mode: 0644]
dc/numeric.c [new file with mode: 0644]
dc/stack.c [new file with mode: 0644]
dc/string.c [new file with mode: 0644]
doc/Makefile.am [new file with mode: 0644]
doc/Makefile.in [new file with mode: 0644]
doc/bc.1 [new file with mode: 0644]
doc/bc.info [new file with mode: 0644]
doc/bc.texi [new file with mode: 0644]
doc/dc.1 [new file with mode: 0644]
doc/dc.info [new file with mode: 0644]
doc/dc.texi [new file with mode: 0644]
doc/texinfo.tex [new file with mode: 0644]
h/getopt.h [new file with mode: 0644]
h/number.h [new file with mode: 0644]
install-sh [new file with mode: 0755]
lib/Makefile.am [new file with mode: 0644]
lib/Makefile.in [new file with mode: 0644]
lib/getopt.c [new file with mode: 0644]
lib/getopt1.c [new file with mode: 0644]
lib/number.c [new file with mode: 0644]
lib/testmul.c [new file with mode: 0644]
lib/vfprintf.c [new file with mode: 0644]
missing [new file with mode: 0755]
mkinstalldirs [new file with mode: 0755]
packaging/bc.changes [new file with mode: 0644]
packaging/bc.manifest [new file with mode: 0644]
packaging/bc.spec [new file with mode: 0644]
stamp-h.in [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..b665a63
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Phil Nelson <philnelson@acm.org> wrote bc, including the number.c
+source in the "lib" directory.
+
+Ken Pizzini wrote dc.
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <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., 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) 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.
diff --git a/COPYING.LIB b/COPYING.LIB
new file mode 100644 (file)
index 0000000..c4792dd
--- /dev/null
@@ -0,0 +1,515 @@
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            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 Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+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 other code 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.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+^L
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  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, whereas the latter must
+be combined with the library in order to run.
+^L
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser 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.
+\f
+  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.
+^L
+  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.
+^L
+  6. As an exception to the Sections above, you may also combine 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) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) 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.
+
+    d) 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.
+
+    e) 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 materials to be 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.
+^L
+  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 with
+this License.
+^L
+  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 Lesser 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.
+^L
+  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
+^L
+           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 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 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 this library; 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.
+
+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!
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..f277079
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1043 @@
+Wed Sep 27 17:19:48 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * doc/bc.texi: Added new file. Mainly translated from bc.1
+                      by Brian Youmans.
+         doc/bc.1: Minor changes made as part of reviewing bc.texi.
+
+Wed Sep 20 11:45:00 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/bc.y:  Added a comment on the meanings of lvals.
+
+Wed Sep 13 11:40:24 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/main.c: add --interactive to long options.
+         bc/bc.1: add -i/--interactive to doc.
+         MANY: Update FSF address and Phil's e-mail.
+       
+Tue Sep 12 13:58:16 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * NEWS: update for recent changes.
+         bc/bc.y: remove required parens around return expression.
+         doc/bc.1: update for recent changes.
+
+Fri Sep  8 10:20:01 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/Makefile.am, dc/Makefile.am, lib/Makefile.am:
+           Compile with unsigned characters.
+         bc/main.c: Add --help option.
+         bc/scan.l: Print illegal, non-printable characters in octal.
+
+Fri Sep  8 09:36:54 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/bc.y: Allow more newlines in function definitions.
+         bc/proto.h: Don't prototype main.
+
+Fri Sep  1 16:09:50 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/bc.y: Spelling correction
+         bc/execute.c: Correct expressions for multi-byte names.
+         bc/load.c: Add parens for correct casting.
+         doc/bc.1: Typos.
+         Above fixes pointed out by kwzh@gnu.org (Karl Heuer).
+
+Tue Aug 29 23:03:30 PDT 2000 Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/testmul.c: #ifdef out a declaration matching #ifdef out
+         code.
+
+Mon Jul 31 07:01:42 2000 Ken Pizzini <ken@gnu.org>
+
+       * dc/numeric.c: use of the "n" command can cause a number to be printed
+         without a trailing newline, which would cause the column counter to
+         fail to be reset and result in inappropriately wrapped numeric outputs.
+         Fixed by always clearing the column counter before outputting each number.
+
+       * dc/stack.c: if a stack is used without ever using the correspondingly
+         named register, it is perfectly legitimate for the register to be
+         uninitialized; added an "else if" to handle this case without aborting.
+
+       * dc/eval.c: updated the comment explaining the restrictions
+         on the | command to better reflect reality.
+
+       * doc/dc.texi: update the FSF office address in the copyright notice
+
+Thu Jul 13 18:13:00 2000 Phil Nelson  <phil@cs.wwu.edu>
+
+       * README: note --with-libedit configure parameter.
+
+Tue Jun 20 22:52:10 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/bcdefs.h: Include <readline/history.h> to quiet warnings. 
+
+       * configure.in: make --with-readline and --with-libedit work correctly.
+
+       * Makefile.am: use $(MAKE) instead of directly calling make.
+
+       * lib/testmul.c: Update to use bc_ on all number.c routines.
+
+Sat Jun 10 22:44:29 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/Makefile.am: Add scan.c to maintainer-clean target.
+
+       * acconfig.h configure.in stamp-h.in bc/Makefile.am bc/execute.c
+         bc/fix-libmath_h bc/global.c bc/load.c bc/main.c bc/storage.c:
+           Remove long string for libmath.  Clean up for compiler errors.
+
+       * dc/numeric.c: Correct parameter name.
+
+Wed May 10 15:51:16 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * {bc,doc,dc,lib}/Makefile.am: Add Makefile.in to maintainer-clean.
+
+       * bootstrap.sh: Added script to run the auto* tools.
+
+       * Imported all into CVS tree.
+
+Sun 2000-05-07  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/Makefile.am, dc/Makefile.am, lib/Makefile.am: Add -Wall to CFLAGS.
+
+       * bc/{execute.c,proto.h,storage.c,util.c}, dc/numeric.c: Changes for
+         -Wall and for name changes in lib/number.c.  (Added bc_ to several
+         routine.  Updated copyright notice.)
+
+       * h/number.h, lib/number.c:  Now comes from bcmath library which is  
+         distributed in a different place. 
+
+Wed Mar 29 17:47:34 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/{bc.y,bcdefs.h,global.h,main.c,proto.h,scan.l,storage.c}:
+         Added BSD libedit support.  Generic support for both where possible.
+         Fixed bugs in readline support noticed during libedit addition.
+         Works with NetBSD-1.4.1 libedit.
+       * doc/bc.1: Documented libedit addition.
+
+Wed Mar 29 10:20:18 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * FAQ: Added this file.
+       * Makfile.am: Added FAQ to distribution
+
+Tue Mar 28 13:52:35 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/number.c, h/number.h: Moved definitions so 
+         number.c/number.h is a stand-alone "library".
+         Changed definition of out_num to not reference a global.
+       * lib/testmul.c: updated #includes for number.h changes.
+       * h/{bcdefs.h,const.h,global.h,proto.h} moved to
+         bc where they really belong.
+       * bc/execute.c: Changed calls to out_num for correctness.
+       * dc/numeric.c: Changed calls to out_num for correctness,
+         include only number.h now and not all the other junk.
+       * configure.in, acconfig.h: Start of support for BSD libedit,
+         added --with-pkg for NetBSD /usr/pkg tree.
+
+Tue Mar 28 11:20:00 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Test/{exp.b,fact.b,jn.b,mul.b,raise.b}: Tweeks on the tests
+         run to do more computation and test the recursive multiply.
+       * bc/scan.l: Removed a printf('\r') that was unneeded.
+
+Mon Mar 27 14:00:00 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * NEWS: Updated for 1.06.
+       * lib/number.c, h/number.h: Fixed bugs in recursive multiply.
+               Changed these files to be under the LGPL.
+       * Tests/jn.b: Added more tests.
+       * lib/Makefile.am: Only generate a timed version of number.o if
+               requested.
+       * README: Updated with information on how to generate a timed
+               version of number.o.
+       * h/version.h: Updated copyright and version number for dc.
+
+Thu Mar 16 14:01:45 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * doc/bc.1, doc/dc.1, doc/dc.texi: Changed bug reporting address
+         to bug-bc@gnu.org to update with what we hope will be reality.
+
+Tue Feb  8 08:54:19 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * doc/bc.1, bc/util.c: Removed "multiply digits"
+         limit due to new recursive algorithm that doesn't
+         have those limits.
+
+Tue Feb  8 08:47:05 2000  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/Makefile.am, lib/testmul.c, lib/number.c, Makefile.am:
+         Finally got a resonable version of the program
+         to test the crossover between non-recursive and
+         recursive multiply algorithms.  Added to distribution
+         and build process.  Does increase build time by 
+         about 10 minutes.
+
+Wed Oct  6 13:28:59 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/Makefile.am: Added rules to allow DEFSADD definitions.
+
+Sat Oct  2 19:59:51 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/libmath.b: Correctly do the cosine accuracy.
+
+Fri Oct  1 12:41:51 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/number.c: Increase accuracy of computing raise.
+         Also turn off use of recursive multiply routines
+         until furthur testing.
+       * bc/libmath.b: Increase accuracy of cosine.
+       * bc/Makefile.am: Remove -lfl from items to make.
+
+Wed Jul 28 10:29:28 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/scan.l:  rl_len from char to int.  (From FreeBSD
+         bug tracking system and Nick Hibma <nick.hibma@jrc.it>)
+
+Tue Jun 22 08:00:28 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/number.c: Rewrote bc_multiply to use a faster
+         algorithm.  Old code not removed yet.
+
+Mon Jun 21 03:08:02 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * h/version.h: Updated version number to 1.06.
+         bc/bc.y: Corrected bug in for statement, not popping.
+         bc/execute.c: Improved stack dump/instruction tracing.
+
+Tue Jun 15 22:30:42 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * configure.in: Updated bc version to 1.06.
+
+Tue Jun 15 22:27:44 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * h/bcdefs.h, h/const.h, bc/execute.c, bc/load.c, bc/storage.c,
+         bc/util.c: Removed segmented function storaged.  Now
+         dynamically expands (by doubling, starting at 1024 bytes)
+         to allow arbitrary sized functions.
+
+Thu Jun 10 22:33:44 1999  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/libmath.b: change scaling in computation of j(n,x) so
+         it correctly computes the value.
+
+Wed Jun 10 10:10:10 1998 Release of bc-1.05a.
+
+Fri Apr 17 10:40:59 1998  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/main.c: Enable readline only if interactive.
+
+Thu Apr 16 16:49:22 1998  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/configure.in: Tweeking of AM_PROG_LEX and associated 
+         special case goo for solaris.
+
+Sat Mar 28 21:43:18 1998  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/Makefile.am: Added "YFLAGS = -d" to get bc.h to build properly.
+
+Mon Mar  9 12:54:42 PST 1998  Ken Pizzini <ken@halcyon.com>
+
+       * doc/dc.texi, doc/dc.1: correct some documentation bugs.
+
+Sun Mar  8 23:56:24 PST 1998  Ken Pizzini <ken@halcyon.com>
+
+       * dc/numeric.c: eliminate superfluous variable from dc_dump_num();
+         annotate unused parameters in dc_add() and dc_sub().
+
+       * h/version.h: change dc version number to 1.2 for release.
+
+Sun Mar  8 21:13:50 1998  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/main.c: Applied patch from Ken Pizzini to force line
+         mode buffering on stdout.
+
+Tue Jan  6 09:15:04 PST 1998  Ken Pizzini <ken@halcyon.com>
+
+       * h/version.h: dc is now up to version 1.1.5.
+
+       * dc/eval.c, dc/numeric.c, doc/dc.texi, doc/dc.1: once again
+         changed the behavior of the 'P' command with a numeric argument
+         to make it more general.  It now dumps out the *whole* number
+         (or rather, the whole of its positive integer portion) as a
+         byte stream.  (For small values this is still the same as 'aP'.)
+
+       * dc/dc-proto.h, dc/dc.h, dc/eval.c, dc/misc.c, dc/numeric.c,
+         dc/stack.c, dc/string.c: Changed most uses of dc_boolean to
+         either dc_discard or dc_newline, and instances of DC_TRUE and
+         DC_FALSE to appropriate instances of DC_TOSS, DC_KEEP, DC_NONL,
+         or DC_WITHNL so that the code self-documents a little better.
+
+Sun Jan  4 15:39:46 PST 1998  Ken Pizzini <ken@halcyon.com>
+
+       * dc/eval.c, doc/dc.texi, doc/dc.1: Changed the functionality
+         of the 'P' command, and added the 'n' command.  Due to
+         a quirk of the implementation of traditional dc, some
+         people have come to expect that the 'P' command on a
+         numeric argument in the range of 1 to 99 should output
+         the corresponding character, despite the fact that this
+         usage can have very weird results for numbers outside
+         that range.  This functionality is why the 'a' command
+         was introduced last March, but people really want it to
+         "just work" without needing to use the 'a' command.
+         Bowing to this demand, the 'P' command now does the
+         equivalent of "aP" if the argument is numeric, and the
+         'n' command has been added to support the previous
+         functionality of the 'P' command.
+
+       * dc/misc.c, dc/eval.c, dc/stack.c, dc/dc-proto.h:
+         Changed prototype for dc_print().  It now additionally
+         takes two flags, newline_p and discard_p, which it
+         passes through to dc_out_num() and dc_out_str() as
+         needed.
+
+       * h/version.h: dc is now up to version 1.1.4.
+
+Sat Sep 27 13:48:53 1997  Ken Pizzini <ken@halcyon.com>
+
+       * h/version.h: dc is now up to version 1.1.3.
+
+       * dc/stack.c, dc/array.c, dc/dc-proto.h, doc/dc.texi, doc/dc.1:
+         It has come to my attention that, though undocumented,
+         traditional dc stacked its arrays in parallel with the
+         stacking of simple registers.  I have now duplicated
+         this functionality.
+
+       * dc/dc.c, configure.in: line-buffer dc's output if setvbuf()
+         is supported.  This was requested to simplify using dc as
+         an inferior process under emacs.
+
+Fri Sep 26 19:56:15 1997  Ken Pizzini <ken@halcyon.com>
+
+       * dc/dc.c: fixed bug reporting address for --help.
+
+       * doc/dc.1, doc/dc.texi: corrected documentation of the maximum
+         admissible input base.
+
+       * doc/dc.texi: corrected sample code equivalence for the | command.
+
+       * lib/number.c: added a warning for non-zero scale in the base
+         for bc_raisemod().
+
+Fri Sep 26 18:15:31 1997  Ken Pizzini <ken@halcyon.com>
+
+       * dc/eval.c, doc/dc.1, doc/dc.texi: added !=, !<, and !> commands.
+
+       * dc/eval.c: eliminated double-free in 'a' command.
+
+       * dc/dc.c: changed placment of check for filename "-" so that
+        "-f -" will work.
+
+       * h/version.h: updated dc version to 1.1.2.
+
+Thu Sep 18 17:41:10 1997  Ken Pizzini <ken@halcyon.com>
+
+       * dc/eval.c: fixed off-by-one error for Q and q commands.
+
+       * dc/dc.c: added missing f: to third argument of getopt().
+
+       * h/version.h: updated dc version to 1.1.1.
+
+Thu May 22 08:24:08 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/number.c(bc_sqrt): Fixed a bug that computed 0 for sqrt
+         of most numbers less than .000001.
+
+Thu May  1 10:41:38 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Test/timetest: change path to bc executable.
+
+Wed Apr 30 12:00:00 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Froze bc-1.04, started new directory for bc-1.05.
+         Fixes to bc-1.04 will be distributed as bc-1.05.
+
+Mon Apr 21 14:57:14 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/scan.l: Changed rules for single line comment to work
+         with lex as well as flex.  Also, do not include \n in the
+         comment.
+
+       * doc/bc.1: Clarified the single line comment and that \n
+         is processed outside of the comment.
+
+Sun Apr 20 22:21:30 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/scan.l: Added rules for a single line comment starting
+         with the # character.
+
+       * doc/bc.1: Documented the single line comment.
+
+       * bc/Makefile.am: Added DISTCLEANFILES for proper clean up.
+
+Sat Apr 19 22:08:05 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * dc/Makefile.am: Removed file from distribution list.
+
+       * h/version.h: Updated dc version to 1.1.
+
+Fri Apr 18 16:43:04 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * lib/number.c (bc_add, bc_sub) Added 1 to the length
+         of the memset call to make sure it zeroed all the
+         storage.
+
+Fri Apr 18 13:58:56 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * configure.in: Tweeks to get things right.  Not sure if things
+         changed much.  Still working with autoconf/automake to do
+         the right thing.
+
+Wed Apr 16 16:49:17 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/main.c (main): Changed processing of BC_ENV_ARGS.
+
+       * bc/main.c (parse_args): Removed "start" parameter.
+
+Tue Apr 15 13:21:28 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * acconfig.h: Included support for PACKAGE and VERSION.
+
+       * configure.in: More tweeks for automake support.
+
+       * h/number.h: Improve definition of MIN and MAX.
+
+       * doc/bc.1: Changed copyright, tweeked other text, added
+         e-mail address for bugs.
+
+       * doc/dc.1: Added copyright and GPL license information,
+         Changed a few .SH formats.
+
+Fri Apr 11 16:14:42 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Makefile.am configure.in doc/Makefile.am lib/Makefile.am
+         bc/Makefile.am bc/bc.y dc/Makefile.am: Changes to accomodate
+         automake-1.1n (pre-release version of automake 1.2).
+
+       * bc/bc.y bc/sbc.y: Changes to make sure tokens are numbered the 
+         same in bc/bc.h and bc/sbc.h.
+
+       * bc/scan.l: Changes for automake's naming convention.
+
+       * NEWS: Fixed a typo.
+
+Thu Apr 10 14:42:55 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/{execute.c, global.c, libmath.b, load.c, main.c, sbc.y
+         scan.l, storage.c, util.c}:  Changed copyright comment and
+         added 1997 to copyright years.
+
+       * h/{bcdefs.h, const.h, global.h, number.h proto.h, version.h}:
+         Changed copyright comment and added 1997 to copyright years.
+
+       * h/version.h: Changed bc version to 1.04.
+
+       * lib/number.c: Changed copyright comment and added 1997 to 
+         copyright years.
+
+       * lib/vfprintf.c: Noted that this was only for minix.
+
+       * NEWS, README: README is now comp.sources.reviewed readme only.
+         NEWS now lists changes from version to version.
+
+Thu Apr 10 13:41:56 1997  Phil Nelson  <phil@fawn.cs.wwu.edu>
+
+       * Makefile.am: Removed FIXME stuff.
+
+Thu Apr 8 13:39:53 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/Makefile.am: Remove files that should not be distributed. 
+
+Mon Apr  7 17:14:28 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Makefile.am: Removed Misc directory from distribution.
+
+Mon Apr  7 16:16:01 1997  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc/sbc.y: Corrected use of nextarg().
+
+Tue Mar 25 19:32:28 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/eval.c, dc/misc.c, dc/stack.c, dc/string.c,
+         dc/dc.h, dc/dc-proto.h, dc/dc.c, dc/numeric.c,
+         doc/dc.texi: updated years in copyright
+         notices.
+
+       * dc/dc.1: updated last-revision date.
+
+Tue Mar 25 16:35:46 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * lib/number.c: give a run-time warning in bc_raisemod()
+         if the modulus does not appear to be an integer.
+
+       * doc/dc.texi, doc/dc.1: documented a warning against
+         the use of the new | command in conjunction with a
+         non-integral modulus.
+
+Tue Mar 25 15:36:04 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/string.c: dc_out_str() updated to use fwrite()
+         instead of printf(), to allow for the existence of
+         a NUL character in the string.
+
+Tue Mar 25 13:42:51 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * doc/dc.texi, doc/dc.1: added documentation for new | command.
+
+Tue Mar 25 13:19:55 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/dc-proto.h: added prototype for dc_triop().
+
+Tue Mar 25 12:00:38 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * lib/number.c: add bc_modexp() modular-exponentiation function.
+
+       * h/proto.h: add prototypes for bc_modexp() and bc_divmod().
+
+Tue Mar 25 09:07:13 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * doc/dc.texi, doc/dc.1: updated documentation with the
+         new command-line options.
+
+       * doc/dc.texi, doc/dc.1: updated documentation with the
+         new '~', 'r', and 'a' commands.
+
+       * dc/dc.c: added bug reporting information to --version text.
+
+Mon Mar 24 19:37:30 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * lib/number.c: added new "bc_divmod" function.
+
+       * dc/numeric.c: added new "dc_divrem" glue function to bc_divmod.
+
+       * dc/stack.c: added new "dc_binop2" function.
+
+       * dc/dc-proto.h: added new prototypes for dc_divrem() and dc_binop2().
+
+       * dc/eval.c, dc/numeric.c: add new '~' command which
+         returns both the quotient and remainder from division.
+
+Mon Mar 24 18:13:42 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/eval.c: Add new 'r' (reverse top two stack elements) command.
+
+Mon Mar 24 17:47:02 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/misc.c: split out the main() related functions into
+         a seperate dc/dc.c file.
+
+       * dc/Makefile.am: updated to reflect this split.
+
+Sat Mar  1 04:57:54 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/misc.c: added "--file" option.
+
+Sat Mar  1 02:13:06 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/eval.c: fixed bug of an excess increment in
+         dc_evalstr()'s DC_COMMENT case.  (Probably would
+         never show up in practice, but did violate the
+         letter of the C Standard.)
+
+       * renamed dc/number.c to dc/numeric.c, to avoid
+         confusion with lib/number.c.
+
+Thu Feb 27 19:45:45 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * dc/string.c, dc/dc.h: changed implementation of dc_str
+         type from a void * to a type which is only completed
+         in dc/string.c.  No functional change, just prettier code.
+
+Thu Feb 27 18:25:19 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * Cleaned up Makefile.am files.
+
+Thu Feb  6 00:41:02 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * Noticed pre-autoconf vestages (NO_XXX configuration options);
+         fixed to refer to autoconf HAVE_XXX definitions.
+
+       * The definition of BC_XXX values in h/const.h might
+         conflict with values of the same name from <limits.h>;
+         fixed to override without spewing warnings.
+
+       * Added check for ptrdiff_t to configure.in; removed
+         special ptrdiff_t definition from dc/string.c .
+
+Wed Feb  5 22:28:37 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * Only compile (guts of) lib/vfprintf.c if system does
+         not have its own version.
+
+Wed Feb  5 22:26:16 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * Changed dc/misc.c source to use standard GNU option
+         parsing routine (instead of special-case code).
+
+       * Added "-e" option to dc.
+
+       * Bumped dc version number to 1.0.4.
+
+Wed Feb  5 22:08:06 1997  Ken Pizzini  <ken@halcyon.com>
+
+       * rearranged source layout (added subdirectory structure);
+         removed "dc-" prefix from dc C source in its new home.
+
+       * merged bc's "version.h" and dc's "dc-version.h" files
+         into h/version.h; patched dc/misc.c to refer to new
+         DC_VERSION macro name.
+
+       * Tweaked configure.in in anticipation of using automake.
+
+Wed Jul 24 16:27:20 1996  Phil Nelson  <phil@cs.wwu.edu>
+
+       * number.c (out_num): Move free of t_num to proper place.
+
+Mon Jun  3 00:31:10 1996  Phil Nelson  <phil@cs.wwu.edu>
+
+       * number.c: (bc_sqrt, is_near_zero) Was hanging in an infinite
+         loop on sqrt(.9999).  Rewrote to take difference.  New routine
+         is_near_zero to check for one digit off.
+
+Thu Feb 22 12:14:38 1996  Phil Nelson  <phil@cs.wwu.edu>
+
+       * dc-eval.c (dc_func): Added the 'a' (number to ascii character)
+         command.
+
+Thu Feb 22 11:55:15 1996  Phil Nelson  <phil@cs.wwu.edu>
+
+       * dc-eval.c: (Changes from Ken) Changes dealing with stdin_lookahead
+         and peekc.
+
+       * dc-misc.c: (Changes from Ken) Changes in option processing.
+
+       * dc-version.c: (Change from Ken) Version is 1.0.2.
+
+Mon Oct  9 15:40:06 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * execute.c (execute): Add a pop to 'W' and 'P' codes.  Otherwise,
+         the stack continues to grow.
+
+       * number.c (out_num): Free all bc_nums used.
+
+Thu Jun 29 00:35:57 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.1: Added information about long options and use of the
+         readline library.
+
+Wed Jun 28 21:03:45 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * scan.l: rl_input: detect EOF.
+
+Wed Jun 28 19:03:51 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Makefile.in: fbc target, changed $(LEXLIB) => $(LIBS)
+
+Wed Jun 28 01:33:07 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * acconfig.h, bc.y, scan.l, storage.c, util.c, configure.in:
+         Improved readline support with a new pseudo variable "history" 
+         that controls the number of history lines available.
+         Also removed "optional" history.
+
+Wed Jun 28 01:03:52 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * getopt.h, getopt.c, getopt1.c: Imported from glibc-1.09
+         to allow long option processing.
+
+       * main.c (parse_args): Make it use long arguments.
+
+       * global.h: Change option flag variables from "char" to "int"
+         to allow long_arguments easy access to the variables.
+
+       * Makefile.in: Add getopt.h, getopt.c, and getopt1.c in the
+         proper places in the Makefile.
+
+Fri Jun 23 12:00:16 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * scan.l, main.c (main), acconfig.h, configure.in:
+         Added support for readline input on stdin.
+
+Thu Jun 22 20:08:57 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.1: Change documentation on POSIX array parameter support.
+
+Fri Apr  7 12:29:28 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * main.c (parse_args): change "char ch" to "int optch" with
+         related changes.
+
+Thu Mar 23 04:11:00 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.1: Update documentation to include new -q
+         option and the environment variables.
+
+Thu Mar 23 03:30:38 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bcdefs.h, global.h, main.c, util.c, bc.y: Reworked
+         argument processing to allow for getting arguments
+         from the environment and the command line.  Added
+         a new mechanism to access file names for opening
+         and for error messages.  Also added a "quiet"
+         option to turn off the welcome banner.
+
+Thu Mar 23 03:12:11 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * util.c: Corrected a comment.
+
+Tue Mar 21 13:36:24 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.y: Added "opt_newline" to allow more newlines
+         in non-POSIX mode.
+
+Tue Mar 21 09:38:28 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * execute.c, main.c, util.c: Add support for user
+         defined line length, "correct POSIX line length",
+         no breaking of strings in std_only mode.  This
+         included adding a new function "out_schar" to
+         util.c.  Also removed "if (interactive)" before
+         all fflushes.
+
+Tue Mar 21 09:12:16 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * global.h: Added new variable "line_size". Cleaned up
+         some definitions by adding comments.
+
+Mon Mar 20 23:33:01 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * proto.h: Define getopt only if no unistd.h file.
+
+Mon Mar 20 23:23:34 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * number.c, proto.h, execute.c, storage.c, dc-number.c:
+         Changes to bc_add and bc_sub parameters to allow for
+         different scale results than were possible.  This is
+         for correct implementation of modulo.  All calls were
+         updated.
+
+Mon Mar 20 19:26:06 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * sbc.y: Removed second parameter on calls to arg_str to match
+         real function.
+
+Tue Feb 28 14:30:18 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * Makefile.in: Change realclean to maintainer-clean.  Added warning. 
+
+Mon Feb 27 17:08:24 1995  Phil Nelson  <phil@cs.wwu.edu>
+
+       * number.c: Change output to conform with POSIX standard for zero
+         only when the -s flag is given.  Otherwise it does the tradational
+         thing.
+
+       * dc-misc.c: Add the "std_only" flag, always set to zero.  This is
+         needed due to the above change.
+
+Tue Nov 29 15:18:20 1994  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.1: Remove the "then" keyword in the if statement documentation.
+
+Mon Nov 28 16:50:25 1994  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.1: Fixed a font change error.
+
+       * Makefile.in: Added missing \ in two targets.
+
+Tue Nov 22 11:09:08 1994  Phil Nelson  <phil@cs.wwu.edu>
+
+       * bc.1: clarified ibase and math routines.
+
+Thu Nov  3 14:09:31 1994  Phil Nelson  (phil@cs.wwu.edu)
+
+       * Makefile.in: added targets uninstall, installdirs and modified
+         other targets to get makes in a directory other than srcdir to
+         work.
+
+       * configure.in: added shell commands to get configure to work
+         correctly in directories other than srcdir.
+
+Wed Nov  2 10:18:19 1994  Phil Nelson  (phil@cs.wwu.edu)
+
+       * bc.1 bc.y bcdefs.h const.h execute.c global.c global.h load.c
+         main.c number.c number.h proto.h sbc.y scan.l storage.c util.c:
+         updated copyright to 1994.
+
+       * version.h: updated version number and copyright date.
+
+       * Makefile.in, configure.in, Install: updated for use with 
+         autoconf-2.0 and install-sh.  Changed target install a bit.
+
+       * install-sh: Included this file from the autoconf-2.0
+         distribution to have configure run without errors.
+
+       * README: updated to version 1.03.
+
+Mon Oct 31 10:26:28 1994  Phil Nelson  (phil@cs.wwu.edu)
+       
+       * Added Ken Pizzini's dc implementation that uses bc numeric
+         routines.  The following files have been added:
+         dc-Concerns   dc-array.c   dc-eval.c   dc-misc.c    dc-number.c 
+         dc-proto.h    dc-regdef.h  dc-stack.c  dc-string.c  dc-version.h
+         dc.1          dc.h         dc.texinfo
+
+       * dc-array.c: Added a conditional include of stdlib.h to get
+         size_t defined on my SunOS 4.1.3 system.
+
+       * configure.in: Added support for dc.
+
+       * Makefile.in: Added support for dc.  Added rule to make
+         config.h.in.
+
+Sun Aug  7 15:09:19 1994  Phil Nelson  (phil@cs.wwu.edu)
+
+       * configure.in, Makefile.in, acconfig.h: Add support for autoconf.
+         Removed old Makefile.
+
+Wed Jul 20 22:46:32 1994  Phil Nelson  (phil@cs.wwu.edu)
+
+       * bc.y: change definition of next_label in function definition.
+         Previous value of 0 caused break to not work.  It is now 1.
+
+Fri Apr  8 14:16:37 1994  Phil Nelson  (phil@cs.wwu.edu)
+
+       * Makefile: Change the distribution to include libmath.h.dist
+         which is a copy of libmath.h that has the compiled libmath.b.
+
+Sun Feb 13 01:08:14 1994  Phil Nelson  (phil@cs.wwu.edu)
+
+       * execute.c: Change the string quote characters to be more like
+         C.  \a => alert (bell) \b => backspace and added \q => ".
+
+       * bc.1: Updated information on above changes.
+
+Wed Oct 27 23:34:40 1993  Phil Nelson  (phil@cs.wwu.edu)
+
+       * Makefile: Changed compress to gzip.  Changed the
+         comment and definition of the DOT_IS_LAST compile option.
+
+       * scan.l: Changed DOT_IS_LAST to NO_DOT_LAST and changed
+         the test so "." is the last variable is standard.
+
+Wed May 19 15:15:12 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * number.c: Fixed output of negative numbers in bases other than
+         base 10.
+
+Wed Apr 21 11:56:31 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * bc.1: Changed Steve Sommars e-mail address.
+
+Wed Apr 14 12:13:39 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * sbc.y: removed leading , on first line.
+
+Wed Mar 31 16:12:39 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * bc.1: Updated segment number for function bodies.
+
+Thu Mar 11 15:34:34 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Makefile: added version.h to bc.o's dependency list.
+
+Mon Mar  1 14:00:46 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * util.c: (nextarg) changed parameter "val" to be an int.
+
+Tue Feb 16 10:06:45 1993  Phil Nelson  (phil at cs.wwu.edu)
+
+       * util.c: (call_str, arg_str) added a function call_str that
+         correctly produces the string of argmuent types for a function
+         call.  arg_str produced them in the reverse order.  This
+         eliminated the need for the "comma" argument to arg_str, which
+         was removed.
+
+       * bc.y: changed the calls to arg_str to have only one parameter
+         in the function definition rule and replaced the call to arg_str
+         with call_str in the function call rule.
+
+Tue Nov 24 17:38:40 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Makefile: Added LEXLIB definitions for use with lex.
+
+Thu Oct 22 13:43:16 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * number.c (bc_raise): Rearranged and added code to speed up
+         the computation by not doing unneeded multiplications.
+
+Wed Sep 30 10:43:52 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * global.h: Fixed documentation.
+
+Tue Sep 29 15:27:50 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * storage.c (process_params): Changed processing of more arguments
+         than in a function definition to just a return.  
+
+       * Makefile: Made changes to make it more in conformance with the
+         GNU coding standards.
+
+Tue Jul  7 21:09:07 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (const.h, bc.y, util.c) Added code so that when the math
+         library is loaded, redefinition of any math library function
+         will not cause the other functions to quit working correctly.
+         Before this change, redefining a(x) would cause s(x) and c(x)
+         to quit working and redefining s(x) would cause c(x) to quit
+         working.
+
+Wed Jul  1 14:35:29 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (libmath.b) Changed the calculation of scale for computing
+         e(x) and l(x).  This provides a little more accuracy in the
+         last digit at the expense of a little speed.
+
+       * (Test/checklib.b) Changed tests to be parameterized and test
+         more values.
+
+Thu Jun 25 09:22:59 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (configure) changed the script from looking in the
+         include directory for a .h file to asking cc (gcc) to
+         find the .h file.  This will allow better detection
+         of include files available to the C compiler.
+
+Wed Jun 24 22:11:37 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (bc.y) Added a warning for the "last" variable.
+
+       * (scan.l) Added code to allow for a single dot (.) to be the
+         same as the variable "last".  This is not a "standard" feature,
+         but is provided for those who want it.
+
+       * (Install) Documented the new define for dot (.).
+
+       * (bc.1) Documented the use of dot (.) for "last".
+
+       * (Makefile) Added an easy method for adding extra defines for
+         use during the compile.  Set DOT_IS_LAST as a standard
+         extra define.
+
+       * (number.c) Changed the code for sqrt for better speed.
+
+Mon Jun 22 21:47:05 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Changed the name of math.h to libmath.h to avoid conflict
+         with /usr/include/math.h.  Changed all references to math.h
+         to libmath.h in all files.
+
+       * (configure) Changed the test for long strings accepted by
+         cc to not include libmath.h and thus not need to distribute
+         a file that is generated by the system.
+
+       * (Makefile) Changed PREFIX, BINDIR, LIBDIR, and MANDIR to
+         lower case.
+
+Tue Mar  3 10:16:07 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (main.c) Added missing } at line 140.
+
+       * (version.h) Changed date of version 1.02 to March 3, 1992.
+
+Mon Feb  3 16:07:57 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (version.h) Updated version number and date.
+
+       * (bc.1) Added a new "VERSION" section.
+
+Wed Jan 29 14:13:55 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (execute.c) Removed the setjmp and longjmp calls that may have
+         caused some problems with interrupted programs.
+
+Thu Jan 16 17:08:16 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (Makefile) Changed install to install the manual.
+
+Wed Jan  8 13:23:42 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Change all copyright notices to include 1992.
+       
+       * (load.c) Added termination to "load_code" to ignore code
+         after an error has been found.
+
+       * (scan.l) Changed the check for NUL characters in STRING tokens
+         (before the close quote) to work correctly.  Also added code to
+         report illegal characters in a more readable output format.
+
+       * (bc.1) Added the exclusion of NUL characters from strings in
+         the "differences" section and updated date of last change.
+
+       * (const.h) Changed BC_MAX_SEGS to 16.
+
+Mon Jan  6 14:20:02 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (number.c) Changed the out_num routine to use a correct field
+         size for bases greater than 16.  e.g.  For base 1000, each
+         "digit" is a three digit number.
+
+       * (Makefile) Added the "8" flag to get an 8 bit scanner.
+
+       * (scan.l) Changed "char *" to "unsigned char *" to match the
+         declaration of yytext for the 8 bit scanner.  Also added code
+         to detect the null character in strings and generate an error.
+
+Sat Jan  4 20:32:20 1992  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (const.h) Changed BC_BASE_MAX to INT_MAX to allow more bases!
+
+Mon Dec 30 21:47:28 1991  Phil Nelson  (phil at cs.wwu.edu)
+
+       * (main.c) Fixed the bug that loaded the math library before
+         every file.
+
+       * (bc.y) Removed some type declarations that duplicated token
+         definitions so it could be run through bison.
+
+       * (load.c) Added a check for maximum code size.
+
+       * (Makefile) Added a prefix for LIBDIR and BINDIR so it can be
+         changed easily.
+
+Mon Nov 25 13:11:17 1991  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Changed version number in version.h to 1.01 with current date.
+
+       * Changed LIBFILE definition in Makefile.
+
+       * Added a recursive function example to bc.1.
+
+Sun Nov 24 21:24:01 1991  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Changed the Makefile to make sure configure is run first.
+         Added the $(CC) the configure call.  Moved some defines
+         toward the front of the Makefile to make sure they are
+         read by installers.  Also added SUBDIRS variable and updated
+         the GNU distribution to include the subdirectories.  Included
+         math.h in the distribution for use by configure.  Included
+         ChangeLog in the distribution.
+
+       * Split the README into README and Install.  Changed Install
+         to have current information.  Documented the STRINGS_H define.
+         Updated the version number in README.
+
+       * Added a check for <strings.h> in configure.
+
+Fri Nov 22 15:06:32 1991  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Changed configure to check for varargs.h first.  Also, added
+         checks to see if long strings (math.h) are accepted by the
+         C compiler.  Also added parameters to configure.
+
+       * Deleted #include <sys/types.h> from proto.h.  Also made only
+         ANSI C compilers include <stdlib.h>.
+
+       * Changed the Makefile to have the install bin directory be
+         /usr/local/bin and the install lib directory be /usr/local/lib.
+
+       * Changed some files in the Test directory to eliminate the
+         <op>= form that some older bcs don't like.
+
+       * Made some small corrections in bc.1.
+
+Tue Oct 29 10:06:32 1991  Phil Nelson  (phil at cs.wwu.edu)
+
+       * Called current version 1.00.
+
+       * Submitted GNU bc-1.00 to comp.sources.reviewed
diff --git a/Examples/ckbook.b b/Examples/ckbook.b
new file mode 100644 (file)
index 0000000..5815ea0
--- /dev/null
@@ -0,0 +1,16 @@
+scale=2
+print "\nCheck book program!\n"
+print "  Remember, deposits are negative transactions.\n"
+print "  Exit by a 0 transaction.\n\n"
+
+print "Initial balance? "; bal = read()
+bal /= 1
+print "\n"
+while (1) {
+  "current balance = "; bal
+  "transaction? "; trans = read()
+  if (trans == 0) break;
+  bal -= trans
+  bal /= 1
+}
+quit
diff --git a/Examples/pi.b b/Examples/pi.b
new file mode 100644 (file)
index 0000000..0d840cf
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+   This is a program to determine the distribution of digits in the
+   fraction part of PI.   It will look at the first scale digits.
+
+   The results are left in the global variable digits.
+   digits[0] is the number of 0's in PI.
+
+   This program requires the math library.
+*/
+
+define pi () {
+  auto ix, pi, save_scale, work;
+
+  save_scale = scale;
+  scale += 5;
+  print "\n\nCalculating PI to ",scale," digits.  Please wait . . .";
+  pi = 4*a(1);
+  scale -= 5;
+  work = pi;
+
+  print "\nCounting digits. . .";
+  for (ix = 0; ix < 10; ix++) digits[ix] = 0;
+
+  /* Extract the One's digit from pi. */
+  scale = 0;
+  one_digit = work / 1;
+
+  for (ix = save_scale; ix > 0; ix--) {
+
+    /* Remove the One's digit and multiply by 10. */
+    scale = ix;
+    work = (work - one_digit) / 1 * 10;
+
+    /* Extract the One's digit. */
+    scale = 0;
+    one_digit = work / 1;
+
+    digits[one_digit] += 1;
+  }
+
+  /* Restore the scale. */
+  scale = save_scale;
+
+  /* Report. */
+  print "\n\n"
+  print "PI to ", scale, " digits is:\n", pi/1, "\n\n"
+  print "The frequency of the digits are:\n"
+  for (ix = 0; ix < 10; ix++) {
+    print "    ", ix, " - ", digits[ix], " times\n"
+  }
+
+  print "\n\n"
+}
diff --git a/Examples/primes.b b/Examples/primes.b
new file mode 100644 (file)
index 0000000..2b52ca7
--- /dev/null
@@ -0,0 +1,32 @@
+
+/* An example that finds all primes between 2 and limit. */
+
+define primes (limit) {
+    auto num, p, root, i
+
+    prime[1] = 2;
+    prime[2] = 3;
+    num = 2;
+    if (limit >= 2) print "prime 1 = 2\n"
+    if (limit >= 3) print "prime 2 = 3\n";
+    scale = 0;
+
+    for ( p=5; p <= limit; p += 2)  {
+       root = sqrt(p);
+       isprime = 1;
+       for ( i = 1;  i < num && prime[i] <= root; i++ ) {
+           if ( p % prime[i] == 0 ) {
+               isprime = 0;
+               break;
+            }
+       }
+       if (isprime) {
+           num += 1;
+           prime [num] = p;
+           print "prime ", num, " = ", p, "\n"
+       }
+     }
+}
+
+
+print "\ntyping 'primes (10)' will print all primes less than 10.\n"
diff --git a/Examples/twins.b b/Examples/twins.b
new file mode 100644 (file)
index 0000000..de910a7
--- /dev/null
@@ -0,0 +1,40 @@
+
+/* An example that finds all primes between 2 and limit. */
+
+define primes (limit) {
+    auto num, p, root, i
+
+    prime[1] = 2;
+    prime[2] = 3;
+    num = 2;
+    scale = 0;
+
+    for ( p=5; p <= limit; p += 2)  {
+       root = sqrt(p);
+       isprime = 1;
+       for ( i = 1;  i < num && prime[i] <= root; i++ ) {
+           if ( p % prime[i] == 0 ) {
+               isprime = 0;
+               break;
+            }
+       }
+       if (isprime) {
+           num += 1;
+           prime [num] = p;
+       }
+     }
+}
+
+
+print "\ntyping 'twins (10)' will print all twin primes less than 10.\n"
+
+define twins (limit) {
+   auto i;
+
+   i = primes(limit+2);
+
+   for (i=1; prime[i] > 0; i++) {
+      if ((prime[i]+2) == prime[i+1]) \
+       print "twins are ", prime[i], " and ", prime[i+1], "\n"
+   }
+}
diff --git a/FAQ b/FAQ
new file mode 100644 (file)
index 0000000..32dd051
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,17 @@
+Because of frequent questions ....... here is the BC FAQ
+
+
+1) Why does BC have its own arbitrary precision number routines 
+   (found in lib/number.c) rather than using GMP?
+
+GMP has "integers" (no digits after a decimal), "rational numbers"
+(stored as 2 integers) and "floats".  None of these will correctly
+represent a POSIX BC number.  Floats are the closest, but will not
+behave correctly for many computations.  For example, BC numbers have
+a "scale" that represent the number of digits to represent after the
+decimal point.  The multiplying two of these numbers requires one to
+calculate an exact number of digits after the decimal point regardless
+of the number of digits in the integer part.  GMP floats have a
+"fixed, but arbitrary" mantissa and so multiplying two floats will end
+up dropping digits BC must calculate.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..3b50ea9
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,176 @@
+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, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+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 a while.  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.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+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 supports 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.
+
+   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' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+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 host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..6703d74
--- /dev/null
@@ -0,0 +1,18 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = lib bc dc doc
+
+MAINTAINERCLEANFILES =  aclocal.m4 config.h.in configure Makefile.in \
+                       $(distdir).tar.gz h/number.h
+
+dist-hook:
+       mkdir $(distdir)/h $(distdir)/Examples $(distdir)/Test
+       cp -p $(srcdir)/h/*.h $(distdir)/h
+       cp -p $(srcdir)/Examples/*.b $(distdir)/Examples
+       cp -p $(srcdir)/Test/*.b $(srcdir)/Test/*.bc $(distdir)/Test
+       cp -p $(srcdir)/Test/signum $(srcdir)/Test/timetest $(distdir)/Test
+       cp -p $(srcdir)/lib/testmul.c $(distdir)/lib
+       cp -p $(srcdir)/FAQ $(distdir)
+
+timetest:
+       (cd lib; $(MAKE) specialnumber)
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..b57eae5
--- /dev/null
@@ -0,0 +1,368 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = .
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+LEX = @LEX@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+READLINELIB = @READLINELIB@
+VERSION = @VERSION@
+YACC = @YACC@
+
+SUBDIRS = lib bc dc doc
+
+MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in                    $(distdir).tar.gz h/number.h
+
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = 
+DIST_COMMON =  README ./stamp-h.in AUTHORS COPYING COPYING.LIB ChangeLog \
+INSTALL Makefile.am Makefile.in NEWS acconfig.h aclocal.m4 config.h.in \
+configure configure.in install-sh missing mkinstalldirs
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(ACLOCAL_M4):  configure.in 
+       cd $(srcdir) && $(ACLOCAL)
+
+config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
+       cd $(srcdir) && $(AUTOCONF)
+
+config.h: stamp-h
+       @if test ! -f $@; then \
+               rm -f stamp-h; \
+               $(MAKE) stamp-h; \
+       else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES= CONFIG_HEADERS=config.h \
+            $(SHELL) ./config.status
+       @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+       @if test ! -f $@; then \
+               rm -f $(srcdir)/stamp-h.in; \
+               $(MAKE) $(srcdir)/stamp-h.in; \
+       else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
+       cd $(top_srcdir) && $(AUTOHEADER)
+       @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+       -rm -f config.h
+
+maintainer-clean-hdr:
+
+# 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.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive  \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       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) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       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:
+       @set fnord $(MAKEFLAGS); amf=$$2; \
+       dot_seen=no; \
+       rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+         rev="$$subdir $$rev"; \
+         test "$$subdir" = "." && dot_seen=yes; \
+       done; \
+       test "$$dot_seen" = "no" && 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) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+   if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+   fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
+
+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_ENV) $(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) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) dist
+       -rm -rf $(distdir)
+       @banner="$(distdir).tar.gz is ready for distribution"; \
+       dashes=`echo "$$banner" | sed s/./=/g`; \
+       echo "$$dashes"; \
+       echo "$$banner"; \
+       echo "$$dashes"
+dist: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
+       -rm -rf $(distdir)
+dist-all: distdir
+       -chmod -R a+r $(distdir)
+       GZIP=$(GZIP_ENV) $(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); \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+       for subdir in $(SUBDIRS); do \
+         if test "$$subdir" = .; then :; else \
+           test -d $(distdir)/$$subdir \
+           || mkdir $(distdir)/$$subdir \
+           || exit 1; \
+           chmod 777 $(distdir)/$$subdir; \
+           (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
+             || exit 1; \
+         fi; \
+       done
+       $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+all-recursive-am: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+install-exec-am:
+install-exec: install-exec-recursive
+
+install-data-am:
+install-data: install-data-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am:
+uninstall: uninstall-recursive
+all-am: Makefile config.h
+all-redirect: all-recursive-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+mostlyclean-am:  mostlyclean-hdr mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am:  clean-hdr clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am:  distclean-hdr distclean-tags distclean-generic clean-am
+
+distclean: distclean-recursive
+       -rm -f config.status
+
+maintainer-clean-am:  maintainer-clean-hdr maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f config.status
+
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+install-data-recursive uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive 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 info-am info \
+dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all installdirs-am \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+dist-hook:
+       mkdir $(distdir)/h $(distdir)/Examples $(distdir)/Test
+       cp -p $(srcdir)/h/*.h $(distdir)/h
+       cp -p $(srcdir)/Examples/*.b $(distdir)/Examples
+       cp -p $(srcdir)/Test/*.b $(srcdir)/Test/*.bc $(distdir)/Test
+       cp -p $(srcdir)/Test/signum $(srcdir)/Test/timetest $(distdir)/Test
+       cp -p $(srcdir)/lib/testmul.c $(distdir)/lib
+       cp -p $(srcdir)/FAQ $(distdir)
+
+timetest:
+       (cd lib; $(MAKE) specialnumber)
+
+# 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:
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..fc02a0d
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,68 @@
+This is GNU bc version 1.06.  (And dc version 1.2)
+
+Changes in dc from 1.2 to 1.3:
+    Minor bug fixes.
+    New multiply algorithm of bc.
+
+Changes in bc from 1.05 to 1.06:
+    New multiply algoirthm and many other changes in lib/number.c
+    Function size now done dynamically.
+    Function syntax in non-posix mode allows newlines in more places.
+    Bug fixes:
+       improved computation of j(n,x).
+       enables readline only if interactive.
+       for statment bug fixed.
+       use int instead of char for readline char counts.
+       improved cosine accuracy.
+
+Changes in dc from 1.1 to 1.2:
+    added !< != !> commands
+    arrays now stack
+    output is now line buffered, provided setvbuf() is available
+    fixed known bugs in 'q', 'Q', 'a' commands, '-f' command-line option,
+      and documentation
+       changed the 'P' command's behavior on a numeric argument:
+         due to popular demand it now does the equivalent of 'aP'
+         (for small values)
+       added new 'n' command to do what the old 'P' command did
+
+Changes in bc from 1.04 to 1.05:
+    Solaris makes work better.
+    bug fixes
+       stdout now always does line buffering.
+       sqrt bug fixed for small numbers.
+       readline (if support is compiled in) is enabled only for
+               interactive executions of bc.
+
+
+This is GNU bc version 1.04.  (And dc version 1.1)
+
+Changes from 1.03
+
+       reorganization of source tree
+       use of automake
+
+       new commands for dc (|, ~, r, a)
+       new command line options for dc
+
+       fixed infinite loop in sqrt in bc
+       fixed an I/O bug in bc
+       made bc conform to POSIX for array parameters
+       added long option support for bc
+       new commandline options for bc (-q)
+       added support for readline to bc (use configure --with-readline)
+       command line argumens can now be taken from an environment variable
+       
+
+Changes from 1.02
+
+       minor bug fixes in bc.
+
+       addition of Ken Pizzini's dc program that uses the GNU bc 
+       arbitrary precision arithmetic routines.
+
+Changes from 1.01
+       
+       minor bug fixes.
+
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..2813fb8
--- /dev/null
+++ b/README
@@ -0,0 +1,86 @@
+GNU bc version 1.06:
+
+Extra configuration options:
+
+       --with-readline tells bc to use the readline package that allows
+         for editing input lines when run interactive.
+
+       --with-editline tells bc to use the BSD editline package that
+         allows for editing input lines when run interactive.
+
+Extra make steps:
+
+       The simple make compiles a version of bc with fixed parameters
+       for the recursive multiplication algorithm.  The fixed parameter
+       is the number of digits where a sequential algorithm is used
+       instead of the recursive algorithm.  It is set to a value that
+       is known good on a couple of machines. (Sparc Ultra 10, Pentium
+       II, 450.)  I'm calling this point the crossover point.
+
+       To make a version of bc with a custom crossover point for your
+       machine, do the following steps:
+
+               make timetest
+               make
+
+       The timetest step takes a minimum of 10 minutes to complete.
+
+
+-------- Original comp.sources.reviewed README --------
+
+Program: GNU bc
+Author: Philip A. Nelson
+E-mail: phil@cs.wwu.edu
+OS: UNIX (BSD, System V, MINIX, POSIX)
+Copying: GNU GPL version 2
+Copyright holder: Free Software Foundation, Inc. 
+Version: bc version 1.01
+Required: vsprintf and vfprintf routines.
+Machines: It has been compiled and run on the following environments:
+       BSD4.3 (VAX 11)
+       MINIX 1.5 (IBM PC, both K&R and ANSI compilers)
+       MINIX 1.5 (pc532)
+       SUN-OS 4.1 (SUN 3 and SUN 4)
+       SVR3V5 (Motorola 68K)
+       SVR3.2 (3B2)
+       SVR4.0.2 (a 386 box)
+       ULTRIX 4.1 (DEC 5000)
+       UTS (Amdahl)
+
+bc is an arbitrary precision numeric processing language.  Syntax is
+similar to C, but differs in many substantial areas.  It supports
+interactive execution of statements.  bc is a utility included in the
+POSIX P1003.2/D11 draft standard.
+
+This version was written to be a POSIX compliant bc processor with
+several extensions to the draft standard.  Option flags are available
+to cause warning or rejection of the extensions to the POSIX standard.
+For those who want only POSIX bc with no extensions, a grammar is
+provided for exactly the language described in the POSIX document.
+The grammar (sbc.y) comes from the POSIX document.  The Makefile
+contains rules to make sbc.  (for Standard BC)
+
+Since the POSIX document does not specify how bc must be implemented,
+this version does not use the historical method of having bc be a
+compiler for the dc calculator.  This version has a single executable
+that both compiles the language and runs the a resulting "byte code".
+The "byte code" is NOT the dc language.
+
+Also, included in the initial distribution is the library file
+vfprintf.c for MINIX systems.  My minix 1.5 did not have this file.
+Also, you should verify that vsprintf.c works correctly on your
+system.
+
+The extensions add some features I think are missing.  The major
+changes and additions for bc are (a) names are allowed to be full
+identifiers ([a-z][a-z0-9_]*), (b) addition of the &&, ||, and !
+operators, (c) allowing comparison and boolean operations in any
+expression, (d) addition of an else clause to the if statement, (e)
+addition of a new standard function "read()" that reads a number from
+the standard input under program control, (f) passing of arrays as
+parameters by variable, (g) addition of the "halt" statement that is
+an executable statement unlike the quit (i.e.  "if (1 == 0) quit" will
+halt bc but "if (1 == 0) halt" will not halt bc.), and (h) the
+addition of the special variable "last" that is assigned the value of
+each print as the number is printed.
+-----------------------------------------------------------------------
diff --git a/Test/BUG.bc b/Test/BUG.bc
new file mode 100644 (file)
index 0000000..254eefe
--- /dev/null
@@ -0,0 +1,40 @@
+/* <--- bug.bc ---><--- bug.bc ---><--- bug.bc ---><--- bug.bc ---> */
+
+/*
+ *  See the file "signum" for a description and reference for this
+ *  program.  
+ *
+ *  THIS BUG IS *NOT* IN GNU BC!!!
+ *
+ */
+
+obase=16
+ibase=16
+x=1A8F5C99605AE52      /* dividend                     */
+y=BB0B404              /* divisor                      */
+q=245A07AD             /* (correct) quotient           */
+r=147EB9E              /* (correct) remainder          */
+"Base 16
+"
+"x    = "; x           /* output numbers just to be sure... */
+"y    = "; y
+"quo  = "; q
+"rem  = "; r
+"x/y  = "; x/y         /* watch this result! */
+"x%y  = "; x%y         /* watch this result! */
+"y*q+r= "; y*q+r       /* check quotient & remainder   */
+/*
+ * Do the same thing in base 10:
+ */
+"
+Base 10
+"
+ibase=A
+obase=10
+"x    = "; x           /* output numbers just to be sure... */
+"y    = "; y
+"q    = "; q
+"r    = "; r
+"x/y  = "; x/y         /* watch this result! */
+"x%y  = "; x%y         /* watch this result! */
+"y*q+r= "; y*q+r       /* check quotient & remainder   */
diff --git a/Test/array.b b/Test/array.b
new file mode 100644 (file)
index 0000000..a0341ec
--- /dev/null
@@ -0,0 +1,14 @@
+"This tests arrays!
+"
+define p(x,y) {
+  auto i;
+  for (i=x; i<y; i++) a[i];
+}
+
+for (i=0; i<10; i++) a[i] = i;
+j = p(0,10);
+
+for (i=1000; i<1030; i++) a[i] = i;
+j = p(1000,1030);
+j = p(0,10);
+
diff --git a/Test/arrayp.b b/Test/arrayp.b
new file mode 100644 (file)
index 0000000..3f3ca50
--- /dev/null
@@ -0,0 +1,30 @@
+"This tests arrays!
+"
+define p(a[],x,y) {
+  auto i;
+  for (i=x; i<y; i++) a[i];
+}
+
+define m(a[],x,y) {
+  auto i;
+  for (i=x; i<y; i++) a[i] = i;
+}
+
+define m1(*a[],x,y) {
+  auto i;
+  print "m1\n"
+  for (i=x; i<y; i++) a[i] = i;
+}
+
+for (i=0; i<10; i++) a[i] = i;
+j = p(a[],0,10);
+
+j = m(b[],0,10);
+j = p(b[],0,10);
+
+print "---\n";
+j = m1(b[],0,10);
+j = p(b[],0,10);
+
+quit
+
diff --git a/Test/aryprm.b b/Test/aryprm.b
new file mode 100644 (file)
index 0000000..9d3f95b
--- /dev/null
@@ -0,0 +1,16 @@
+define p ( x[] ) {
+  auto i;
+  for (i=0; i<10; i++) x[i];
+}
+
+define m ( x[] ) {
+  auto i;
+  for (i=0; i<10; i++) x[i] *= 2;
+}
+    
+scale = 20;
+for (i=0; i<10; i++) a[i] = sqrt(i);
+
+p(a[]);
+m(a[]);
+p(a[]);
diff --git a/Test/atan.b b/Test/atan.b
new file mode 100644 (file)
index 0000000..e742279
--- /dev/null
@@ -0,0 +1,5 @@
+for (a=0; a<1000; a+=2) x=a(a)
+x
+for (a=0; a<2; a+=.01) x=a(a)
+x
+quit
diff --git a/Test/checklib.b b/Test/checklib.b
new file mode 100644 (file)
index 0000000..44c1fac
--- /dev/null
@@ -0,0 +1,109 @@
+define t (x,y,d,s,t) {
+   auto u, v, w, i, b, c;
+
+   if (s >= t) {
+     "Bad Scales. Try again.
+";   return;
+   }
+
+   for (i = x; i < y; i += d) {
+     scale = s;
+     u = f(i);
+     scale = t;
+     v = f(i);
+     scale = s;
+     w = v / 1;
+     b += 1;
+     if (u != w) {
+       c += 1;
+"
+Failed:  
+"
+       "  index = "; i;
+       "  val1 = "; u;
+       "  val2 = "; v;
+"
+"
+     }
+   }
+
+"
+Total tests:    "; b;
+"
+Total failures: "; c;
+"
+Percent failed: "; scale = 2; c*100/b;
+
+}
+
+/*
+   b = begining scale value, 
+   l = limit scale value,
+   i = increment scale value.
+
+   if b is set to a non-zero value before this file is executed,
+   b, l and i are not reset.
+*/
+
+if (b == 0) { b = 10; l = 61; i = 10; }
+
+"
+Checking e(x)"
+define f(x) {
+  return (e(x))
+}
+for (s=10; s<l; s=s+i) {
+"
+scale = "; s
+j = t(0,200,1,s,s+4)
+}
+
+"
+Checking l(x)"
+define f(x) {
+  return (l(x))
+}
+for (s=10; s<l; s=s+i) {
+"
+scale = "; s
+j = t(1,10000,25,s,s+4)
+}
+
+"
+Checking s(x)"
+define f(x) {
+  return (s(x))
+}
+for (s=10; s<l; s=s+i) {
+"
+scale = "; s
+j = t(0,8*a(1),.01,s,s+4)
+}
+
+"
+Checking a(x)"
+define f(x) {
+  return (a(x))
+}
+for (s=10; s<l; s=s+i) {
+"
+scale = "; s
+j = t(-1000,1000,10,s,s+4)
+}
+
+"
+Checking j(n,x)"
+define f(x) {
+  return (j(n,x))
+}
+for (s=10; s<l; s=s+i) {
+"
+n=0, scale = "; s
+n=0
+j = t(0,30,.1,s,s+4)
+"
+n=1, scale = "; s
+n=1
+j = t(0,30,.1,s,s+4)
+}
+
diff --git a/Test/div.b b/Test/div.b
new file mode 100644 (file)
index 0000000..3c7d377
--- /dev/null
@@ -0,0 +1,8 @@
+scale = 20
+a=2/3
+for (i=0; i<1000; i++) {
+  for (j=1; j<100; j++) b=a/j
+}
+b
+quit
+
diff --git a/Test/exp.b b/Test/exp.b
new file mode 100644 (file)
index 0000000..92c482c
--- /dev/null
@@ -0,0 +1,3 @@
+for (a=0; a<180; a+=.4) x=e(a)
+x
+quit
diff --git a/Test/fact.b b/Test/fact.b
new file mode 100644 (file)
index 0000000..995a26d
--- /dev/null
@@ -0,0 +1,12 @@
+define f (x) {
+
+  if (x<=1) return(1)
+  return (f(x-1)*x)
+}
+
+for (a=1; a<600; a++) b=f(a)
+"
+"
+"b=";b
+quit
+
diff --git a/Test/jn.b b/Test/jn.b
new file mode 100644 (file)
index 0000000..a4e0624
--- /dev/null
+++ b/Test/jn.b
@@ -0,0 +1,6 @@
+scale = 50
+for (a=0; a<=100; a += 20) {
+  for (b=0; b<=300; b += 20) x=j(a,b)
+  x
+}
+quit
diff --git a/Test/ln.b b/Test/ln.b
new file mode 100644 (file)
index 0000000..cd00232
--- /dev/null
+++ b/Test/ln.b
@@ -0,0 +1,4 @@
+scale = 60
+for (a=1; a<100000000000000000000000000000000000000; a = a*2) x=l(a)
+x
+quit
diff --git a/Test/mul.b b/Test/mul.b
new file mode 100644 (file)
index 0000000..722086f
--- /dev/null
@@ -0,0 +1,13 @@
+scale = 20
+for (i=0; i<10000; i++) {
+  for (j=1; j<100; j++) b=i*j
+}
+b
+for (i=0; i<10000; i++) {
+  for (j=1000000000000000000000000000000000000000000000000000000000000000000; \
+       j<1000000000000000000000000000000000000000000000000000000000000000100; \
+       j++) b=i*j
+}
+b
+quit
+
diff --git a/Test/raise.b b/Test/raise.b
new file mode 100644 (file)
index 0000000..ec6929d
--- /dev/null
@@ -0,0 +1,7 @@
+for (i=0; i<1000; i++) a = 2^i;
+a
+for (i=3000; i<3100; i++) a = 3^i;
+a
+for (i=200; i<220; i++) a = (4^100)^i;
+a
+quit
diff --git a/Test/signum b/Test/signum
new file mode 100644 (file)
index 0000000..9e27d2d
--- /dev/null
@@ -0,0 +1,87 @@
+
+
+
+/* From gnu@cygnus.com Wed Jul 14 13:46:44 1993
+Return-Path: <gnu@cygnus.com>
+To: phil@cs.wwu.edu, gnu@cygnus.com
+Subject: bc/dc - no rest for the wicked
+Date: Tue, 06 Jul 93 19:12:40 -0700
+From: gnu@cygnus.com
+
+GNU bc 1.02 passes all these tests.  Can you add the test to the distribution?
+Putting it into a DejaGnu test case for GNU bc would be a great thing, too.
+(I haven't seen the Signum paper, maybe you can dig it out.)
+
+       John Gilmore
+       Cygnus Support
+
+------- Forwarded Message
+
+Date: Tue, 6 Jul 93 08:45:48 PDT
+From: uunet!Eng.Sun.COM!David.Hough@uunet.UU.NET (David Hough)
+Message-Id: <9307061545.AA14477@dgh.Eng.Sun.COM>
+To: numeric-interest@validgh.com
+Subject: bc/dc - no rest for the wicked
+
+Steve Sommars sent me a bc script which reproduces ALL the test cases from
+Dittmer's paper.    Neither SunOS 5.2 on SPARC nor 5.1 on x86 come out clean.
+Anybody else who has fixed all the bugs would be justified in 
+bragging about it here.  */
+
+
+/*Ingo Dittmer, ACM Signum, April 1993, page 8-11*/
+define g(x,y,z){
+       auto a
+       a=x%y
+       if(a!=z){
+"
+x=";x
+       "y=";y
+       "Should be ";z
+       "was       ";a
+       }
+}
+
+/*Table 1*/
+g=g(53894380494284,9980035577,2188378484)
+g=g(47907874973121,9980035577,3704203521)
+g=g(76850276401922,9980035577,4002459022)
+g=g(85830854846664,9980035577,2548884464)
+g=g(43915353970066,9980035577,3197431266)
+g=g(35930746212825,9980035577,2618135625)
+g=g(51900604524715,9980035577,4419524315)
+g=g(87827018005068,9980035577,2704927468)
+g=g(57887902441764,9980035577,3696095164)
+g=g(96810941031110,9980035577,4595934210)
+
+/*Table 2*/
+g=g(86833646827370,9980035577,7337307470)
+g=g(77850880592435,9980035577,6603091835)
+g=g(84836601050323,9980035577,6298645823)
+g=g(85835110016211,9980035577,6804054011)
+g=g(94817143459192,9980035577,6805477692)
+g=g(94818870293481,9980035577,8532311981)
+g=g(91823235571154,9980035577,6908262754)
+g=g(59885451951796,9980035577,5238489796)
+g=g(80844460893239,9980035577,6172719539)
+g=g(67869195894693,9980035577,4953971093)
+g=g(95813990985202,9980035577,5649446002)
+
+/*Skip Table 3, duplicate of line 1, table 1*/
+
+/*Table 4*/
+g=g(28420950579078013018256253301,17987947258,16619542243)
+g=g(12015118977201790601658257234,16687885701,8697335297)
+g=g(14349070374946789715188912007,13712994561,3605141129)
+g=g(61984050238512905451986475027,13337935089,5296182558)
+g=g(86189707791214681859449918641,17837971389,14435206830)
+g=g(66747908181102582528134773954,19462997965,8615839889)
+
+/*Table 6*/
+g=g(4999253,9998,253)
+g=g(8996373,9995,873)
+
+
+/* Added by Phil Nelson..... */
+"end of tests
+"
diff --git a/Test/sine.b b/Test/sine.b
new file mode 100644 (file)
index 0000000..18c4b57
--- /dev/null
@@ -0,0 +1,5 @@
+for (i=0; i<8*a(1); i=i+.01) x=s(i)
+x
+for (i=i; i<16*a(1); i=i+.01) x=s(i+.1234123412341234)
+x
+quit
diff --git a/Test/sqrt.b b/Test/sqrt.b
new file mode 100644 (file)
index 0000000..3fb548c
--- /dev/null
@@ -0,0 +1,13 @@
+scale = 5
+for (a=1; a<500; a++) r=sqrt(a)
+r
+scale = 10
+for (a=1; a<500; a++) r=sqrt(a)
+r
+scale = 25
+for (a=1; a<500; a++) r=sqrt(a)
+r
+scale = 40
+for (a=1; a<500; a++) r=sqrt(a)
+r
+quit
diff --git a/Test/sqrt1.b b/Test/sqrt1.b
new file mode 100644 (file)
index 0000000..c3ca269
--- /dev/null
@@ -0,0 +1,13 @@
+for (j=0; j<10; j++) {
+  a = .9;
+  b = .9+j;
+  scale = 2;
+  for (i=0; i<90; i++) {
+    scale += 1;
+    a /= 10;
+    b += a;
+    x = sqrt(b);
+  }
+  x;
+}
+quit
diff --git a/Test/sqrt2.b b/Test/sqrt2.b
new file mode 100644 (file)
index 0000000..bd0eaad
--- /dev/null
@@ -0,0 +1,10 @@
+scale = 20
+for (a=1; a<5000; a += 1) r=sqrt(a)
+r
+for (a=1; a<50000; a += 100) r=sqrt(a)
+r
+for (a=1; a<500000; a+=1000) r=sqrt(a)
+r
+for (a=1; a<5000000; a+=10000) r=sqrt(a)
+r
+quit
diff --git a/Test/testfn.b b/Test/testfn.b
new file mode 100644 (file)
index 0000000..7578fc5
--- /dev/null
@@ -0,0 +1,47 @@
+/* This function "t" tests the function "f" to see if computing at
+   two different scales has much effect on the accuracy. 
+   test from f(x) to f(y) incrementing the index by d.  f(i) is
+   computed at two scales, scale s and then scale t, where t>s.
+   the result from scale t is divided by 1 at scale s and the
+   results are compared.  If they are different, the function is
+   said to have failed.  It will then print out the value of i
+   (called index) and the two original values val1 (scale s) and
+   val2 (scale t) */
+
+define t (x,y,d,s,t) {
+   auto u, v, w, i, b, c;
+
+   if (s >= t) {
+     "Bad Scales. Try again.
+";   return;
+   }
+
+   for (i = x; i < y; i += d) {
+     scale = s;
+     u = f(i);
+     scale = t;
+     v = f(i);
+     scale = s;
+     w = v / 1;
+     b += 1;
+     if (u != w) {
+       c += 1;
+"
+Failed:  
+"
+       "  index = "; i;
+       "  val1 = "; u;
+       "  val2 = "; v;
+"
+"
+     }
+   }
+
+"
+Total tests:    "; b;
+"
+Total failures: "; c;
+"
+Percent failed: "; scale = 2; c*100/b;
+
+}
diff --git a/Test/timetest b/Test/timetest
new file mode 100755 (executable)
index 0000000..1a4d0ea
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Time the functions.
+#
+SYSBC=/usr/bin/bc
+if [ x$BC = x ] ; then
+  BC=../bc/bc
+fi
+for file in exp.b ln.b sine.b atan.b jn.b mul.b div.b raise.b sqrt.b
+do
+for prog in $BC $SYSBC $OTHERBC
+do
+echo Timing $file with $prog
+time $prog -l $file
+done
+done
diff --git a/acconfig.h b/acconfig.h
new file mode 100644 (file)
index 0000000..ff17f82
--- /dev/null
@@ -0,0 +1,24 @@
+/* PACKAGE name */
+#undef PACKAGE
+
+/* Package VERSION number */
+#undef VERSION
+
+/* VERSION number for DC target*/
+#undef DC_VERSION
+
+/* COPYRIGHT notice for DC target */
+#undef DC_COPYRIGHT
+
+/* COPYRIGHT notice for BC target */
+#undef BC_COPYRIGHT
+
+/* Define to use the readline library. */
+#undef READLINE
+
+/* Define to use the BSD libedit library. */
+#undef LIBEDIT
+
+/* Define to `size_t' if <sys/types.h> and <stddef.h> don't define.  */
+#undef ptrdiff_t
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..102dc3e
--- /dev/null
@@ -0,0 +1,136 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Do all the work for Automake.  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.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+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
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# 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 conftestfile 2> /dev/null`
+   if test "[$]*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "[$]*" != "X $srcdir/configure conftestfile" \
+      && test "[$]*" != "X conftestfile $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" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+   $1=$2
+   AC_MSG_RESULT(found)
+else
+   $1="$3/missing $2"
+   AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated.  We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+  case " <<$>>CONFIG_HEADERS " in
+  *" <<$>>am_file "*<<)>>
+    echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+    ;;
+  esac
+  am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+
+dnl AM_PROG_LEX
+dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT
+AC_DEFUN(AM_PROG_LEX,
+[missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1)
+AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex")
+AC_PROG_LEX
+AC_DECL_YYTEXT])
+
diff --git a/bc/Makefile.am b/bc/Makefile.am
new file mode 100644 (file)
index 0000000..9187339
--- /dev/null
@@ -0,0 +1,42 @@
+## Process this file with automake to produce Makefile.in
+bin_PROGRAMS = bc
+
+bc_SOURCES = main.c bc.y scan.l execute.c load.c storage.c util.c global.c
+
+EXTRA_DIST = bc.h bcdefs.h const.h fix-libmath_h global.h libmath.b proto.h \
+             sbc.y
+noinst_HEADERS = libmath.h
+
+DISTCLEANFILES = sbc sbc.c sbc.h
+
+MAINTAINERCLEANFILES = Makefile.in libmath.h bc.c bc.h scan.c
+
+INCLUDES = -I$(srcdir) -I$(srcdir)/../h
+LIBBC = ../lib/libbc.a
+LIBL = @LEXLIB@
+LDADD = $(LIBBC) $(LIBL) @READLINELIB@
+
+YFLAGS = -d
+
+CFLAGS = @CFLAGS@ -Wall -funsigned-char
+
+$(PROGRAMS): $(LIBBC)
+
+scan.o: bc.h
+global.o: libmath.h
+
+libmath.h: libmath.b
+       echo '{0}' > libmath.h
+       $(MAKE) fbc
+       ./fbc -c $(srcdir)/libmath.b </dev/null >libmath.h
+       $(srcdir)/fix-libmath_h
+       rm -f ./fbc
+
+fbcOBJ = main.o bc.o scan.o execute.o global.o load.o storage.o util.o
+fbc: $(fbcOBJ)
+       $(LINK) $(fbcOBJ) $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
+
+sbcOBJ = main.o sbc.o scan.o execute.o global.o load.o storage.o util.o
+sbc.o: sbc.c
+sbc: $(sbcOBJ)
+       $(LINK) $(sbcOBJ) $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
diff --git a/bc/Makefile.in b/bc/Makefile.in
new file mode 100644 (file)
index 0000000..18ebce0
--- /dev/null
@@ -0,0 +1,345 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+LEX = @LEX@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+READLINELIB = @READLINELIB@
+VERSION = @VERSION@
+YACC = @YACC@
+
+bin_PROGRAMS = bc
+
+bc_SOURCES = main.c bc.y scan.l execute.c load.c storage.c util.c global.c
+
+EXTRA_DIST = bc.h bcdefs.h const.h fix-libmath_h global.h libmath.b proto.h              sbc.y
+
+noinst_HEADERS = libmath.h
+
+DISTCLEANFILES = sbc sbc.c sbc.h
+
+MAINTAINERCLEANFILES = Makefile.in libmath.h bc.c bc.h scan.c
+
+INCLUDES = -I$(srcdir) -I$(srcdir)/../h
+LIBBC = ../lib/libbc.a
+LIBL = @LEXLIB@
+LDADD = $(LIBBC) $(LIBL) @READLINELIB@
+
+YFLAGS = -d
+
+CFLAGS = @CFLAGS@ -Wall -funsigned-char
+
+fbcOBJ = main.o bc.o scan.o execute.o global.o load.o storage.o util.o
+
+sbcOBJ = main.o sbc.o scan.o execute.o global.o load.o storage.o util.o
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+bc_OBJECTS =  main.o bc.o scan.o execute.o load.o storage.o util.o \
+global.o
+bc_LDADD = $(LDADD)
+bc_DEPENDENCIES =  ../lib/libbc.a
+bc_LDFLAGS = 
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LEXLIB = @LEXLIB@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+HEADERS =  $(noinst_HEADERS)
+
+DIST_COMMON =  Makefile.am Makefile.in bc.c scan.c
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(bc_SOURCES)
+OBJECTS = $(bc_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .l .o .s .y
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps bc/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+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 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+            $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       list='$(bin_PROGRAMS)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+       done
+
+.c.o:
+       $(COMPILE) -c $<
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+bc: $(bc_OBJECTS) $(bc_DEPENDENCIES)
+       @rm -f bc
+       $(LINK) $(bc_LDFLAGS) $(bc_OBJECTS) $(bc_LDADD) $(LIBS)
+.l.c:
+       $(LEX) $(AM_LFLAGS) $(LFLAGS) $< && mv $(LEX_OUTPUT_ROOT).c $@
+.y.c:
+       $(YACC) $(AM_YFLAGS) $(YFLAGS) $< && mv y.tab.c $*.c
+       if test -f y.tab.h; then \
+       if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \
+       else :; fi
+bc.h: bc.c
+
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = bc
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+bc.o: bc.c bcdefs.h ../config.h const.h ../h/number.h global.h proto.h
+execute.o: execute.c bcdefs.h ../config.h const.h ../h/number.h global.h \
+       proto.h
+global.o: global.c bcdefs.h ../config.h const.h ../h/number.h global.h \
+       libmath.h
+load.o: load.c bcdefs.h ../config.h const.h ../h/number.h global.h \
+       proto.h
+main.o: main.c bcdefs.h ../config.h const.h ../h/number.h global.h \
+       proto.h ../h/getopt.h
+scan.o: scan.c bcdefs.h ../config.h const.h ../h/number.h bc.h global.h \
+       proto.h
+storage.o: storage.c bcdefs.h ../config.h const.h ../h/number.h global.h \
+       proto.h
+util.o: util.c bcdefs.h ../config.h const.h ../h/number.h global.h \
+       proto.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+       $(mkinstalldirs)  $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+       -test -z "scanlbchbcc$(MAINTAINERCLEANFILES)" || rm -f scanl bch bcc $(MAINTAINERCLEANFILES)
+mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
+               mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-binPROGRAMS clean-compile clean-tags clean-generic \
+               mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-binPROGRAMS distclean-compile distclean-tags \
+               distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-binPROGRAMS \
+               maintainer-clean-compile maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+$(PROGRAMS): $(LIBBC)
+
+scan.o: bc.h
+global.o: libmath.h
+
+libmath.h: libmath.b
+       echo '{0}' > libmath.h
+       $(MAKE) fbc
+       ./fbc -c $(srcdir)/libmath.b </dev/null >libmath.h
+       $(srcdir)/fix-libmath_h
+       rm -f ./fbc
+fbc: $(fbcOBJ)
+       $(LINK) $(fbcOBJ) $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
+sbc.o: sbc.c
+sbc: $(sbcOBJ)
+       $(LINK) $(sbcOBJ) $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
+
+# 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:
diff --git a/bc/bc.c b/bc/bc.c
new file mode 100644 (file)
index 0000000..6750bb6
--- /dev/null
+++ b/bc/bc.c
@@ -0,0 +1,1886 @@
+
+/*  A Bison parser, made from bc.y
+ by  GNU Bison version 1.27
+  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+#define        ENDOFLINE       257
+#define        AND     258
+#define        OR      259
+#define        NOT     260
+#define        STRING  261
+#define        NAME    262
+#define        NUMBER  263
+#define        ASSIGN_OP       264
+#define        REL_OP  265
+#define        INCR_DECR       266
+#define        Define  267
+#define        Break   268
+#define        Quit    269
+#define        Length  270
+#define        Return  271
+#define        For     272
+#define        If      273
+#define        While   274
+#define        Sqrt    275
+#define        Else    276
+#define        Scale   277
+#define        Ibase   278
+#define        Obase   279
+#define        Auto    280
+#define        Read    281
+#define        Warranty        282
+#define        Halt    283
+#define        Last    284
+#define        Continue        285
+#define        Print   286
+#define        Limits  287
+#define        UNARY_MINUS     288
+#define        HistoryVar      289
+
+#line 1 "bc.y"
+
+/* bc.y: The grammar for a POSIX compatable bc processor with some
+         extensions to the language. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to:
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+
+#line 40 "bc.y"
+typedef union {
+       char     *s_value;
+       char      c_value;
+       int       i_value;
+       arg_list *a_value;
+       } YYSTYPE;
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define        YYFINAL         185
+#define        YYFLAG          -32768
+#define        YYNTBASE        50
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 289 ? yytranslate[x] : 84)
+
+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,     2,     2,     2,     2,    40,     2,     2,    43,
+    44,    38,    36,    47,    37,     2,    39,     2,     2,     2,
+     2,     2,     2,     2,     2,     2,     2,     2,    42,     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,
+    48,     2,    49,    41,     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,    45,     2,    46,     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,     3,     4,     5,     6,
+     7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+    17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+    27,    28,    29,    30,    31,    32,    33,    34,    35
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = {     0,
+     0,     1,     4,     7,     9,    12,    13,    15,    16,    18,
+    22,    25,    26,    28,    31,    35,    38,    42,    44,    47,
+    49,    51,    53,    55,    57,    59,    61,    63,    66,    67,
+    68,    69,    70,    85,    86,    95,    96,    97,   106,   110,
+   111,   115,   117,   121,   123,   125,   126,   127,   132,   133,
+   146,   147,   149,   150,   154,   158,   160,   164,   169,   173,
+   179,   186,   187,   189,   191,   195,   199,   205,   206,   208,
+   209,   211,   212,   217,   218,   223,   224,   229,   232,   236,
+   240,   244,   248,   252,   256,   260,   263,   265,   267,   271,
+   276,   279,   282,   287,   292,   297,   301,   303,   308,   310,
+   312,   314,   316,   318,   319,   321
+};
+
+static const short yyrhs[] = {    -1,
+    50,    51,     0,    53,     3,     0,    69,     0,     1,     3,
+     0,     0,     3,     0,     0,    55,     0,    53,    42,    55,
+     0,    53,    42,     0,     0,    55,     0,    54,     3,     0,
+    54,     3,    55,     0,    54,    42,     0,    54,    42,    56,
+     0,    56,     0,     1,    56,     0,    28,     0,    33,     0,
+    78,     0,     7,     0,    14,     0,    31,     0,    15,     0,
+    29,     0,    17,    77,     0,     0,     0,     0,     0,    18,
+    57,    43,    76,    42,    58,    76,    42,    59,    76,    44,
+    60,    52,    56,     0,     0,    19,    43,    78,    44,    61,
+    52,    56,    67,     0,     0,     0,    20,    62,    43,    78,
+    63,    44,    52,    56,     0,    45,    54,    46,     0,     0,
+    32,    64,    65,     0,    66,     0,    66,    47,    65,     0,
+     7,     0,    78,     0,     0,     0,    22,    68,    52,    56,
+     0,     0,    13,     8,    43,    71,    44,    52,    45,    83,
+    72,    70,    54,    46,     0,     0,    73,     0,     0,    26,
+    73,     3,     0,    26,    73,    42,     0,     8,     0,     8,
+    48,    49,     0,    38,     8,    48,    49,     0,    73,    47,
+     8,     0,    73,    47,     8,    48,    49,     0,    73,    47,
+    38,     8,    48,    49,     0,     0,    75,     0,    78,     0,
+     8,    48,    49,     0,    75,    47,    78,     0,    75,    47,
+     8,    48,    49,     0,     0,    78,     0,     0,    78,     0,
+     0,    82,    10,    79,    78,     0,     0,    78,     4,    80,
+    78,     0,     0,    78,     5,    81,    78,     0,     6,    78,
+     0,    78,    11,    78,     0,    78,    36,    78,     0,    78,
+    37,    78,     0,    78,    38,    78,     0,    78,    39,    78,
+     0,    78,    40,    78,     0,    78,    41,    78,     0,    37,
+    78,     0,    82,     0,     9,     0,    43,    78,    44,     0,
+     8,    43,    74,    44,     0,    12,    82,     0,    82,    12,
+     0,    16,    43,    78,    44,     0,    21,    43,    78,    44,
+     0,    23,    43,    78,    44,     0,    27,    43,    44,     0,
+     8,     0,     8,    48,    78,    49,     0,    24,     0,    25,
+     0,    23,     0,    35,     0,    30,     0,     0,     3,     0,
+    83,     3,     0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+   107,   116,   118,   120,   122,   128,   129,   132,   134,   135,
+   136,   138,   140,   141,   142,   143,   144,   146,   147,   150,
+   152,   154,   163,   170,   180,   191,   193,   195,   197,   202,
+   212,   223,   233,   241,   248,   254,   260,   267,   273,   275,
+   278,   279,   280,   282,   288,   291,   292,   300,   301,   315,
+   321,   323,   325,   327,   329,   332,   334,   336,   338,   340,
+   342,   345,   347,   349,   354,   360,   365,   381,   386,   388,
+   393,   401,   413,   428,   436,   441,   449,   457,   463,   491,
+   496,   501,   506,   511,   516,   521,   526,   535,   551,   553,
+   569,   588,   611,   613,   615,   617,   623,   625,   630,   632,
+   634,   636,   640,   647,   648,   649
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = {   "$","error","$undefined.","ENDOFLINE",
+"AND","OR","NOT","STRING","NAME","NUMBER","ASSIGN_OP","REL_OP","INCR_DECR","Define",
+"Break","Quit","Length","Return","For","If","While","Sqrt","Else","Scale","Ibase",
+"Obase","Auto","Read","Warranty","Halt","Last","Continue","Print","Limits","UNARY_MINUS",
+"HistoryVar","'+'","'-'","'*'","'/'","'%'","'^'","';'","'('","')'","'{'","'}'",
+"','","'['","']'","program","input_item","opt_newline","semicolon_list","statement_list",
+"statement_or_error","statement","@1","@2","@3","@4","@5","@6","@7","@8","print_list",
+"print_element","opt_else","@9","function","@10","opt_parameter_list","opt_auto_define_list",
+"define_list","opt_argument_list","argument_list","opt_expression","return_expression",
+"expression","@11","@12","@13","named_expression","required_eol", NULL
+};
+#endif
+
+static const short yyr1[] = {     0,
+    50,    50,    51,    51,    51,    52,    52,    53,    53,    53,
+    53,    54,    54,    54,    54,    54,    54,    55,    55,    56,
+    56,    56,    56,    56,    56,    56,    56,    56,    57,    58,
+    59,    60,    56,    61,    56,    62,    63,    56,    56,    64,
+    56,    65,    65,    66,    66,    67,    68,    67,    70,    69,
+    71,    71,    72,    72,    72,    73,    73,    73,    73,    73,
+    73,    74,    74,    75,    75,    75,    75,    76,    76,    77,
+    77,    79,    78,    80,    78,    81,    78,    78,    78,    78,
+    78,    78,    78,    78,    78,    78,    78,    78,    78,    78,
+    78,    78,    78,    78,    78,    78,    82,    82,    82,    82,
+    82,    82,    82,    83,    83,    83
+};
+
+static const short yyr2[] = {     0,
+     0,     2,     2,     1,     2,     0,     1,     0,     1,     3,
+     2,     0,     1,     2,     3,     2,     3,     1,     2,     1,
+     1,     1,     1,     1,     1,     1,     1,     2,     0,     0,
+     0,     0,    14,     0,     8,     0,     0,     8,     3,     0,
+     3,     1,     3,     1,     1,     0,     0,     4,     0,    12,
+     0,     1,     0,     3,     3,     1,     3,     4,     3,     5,
+     6,     0,     1,     1,     3,     3,     5,     0,     1,     0,
+     1,     0,     4,     0,     4,     0,     4,     2,     3,     3,
+     3,     3,     3,     3,     3,     2,     1,     1,     3,     4,
+     2,     2,     4,     4,     4,     3,     1,     4,     1,     1,
+     1,     1,     1,     0,     1,     2
+};
+
+static const short yydefact[] = {     1,
+     0,     0,     0,    23,    97,    88,     0,     0,    24,    26,
+     0,    70,    29,     0,    36,     0,   101,    99,   100,     0,
+    20,    27,   103,    25,    40,    21,   102,     0,     0,     0,
+     2,     0,     9,    18,     4,    22,    87,     5,    19,    78,
+    62,     0,    97,   101,    91,     0,     0,    28,    71,     0,
+     0,     0,     0,     0,     0,     0,    86,     0,     0,     0,
+    13,     3,     0,    74,    76,     0,     0,     0,     0,     0,
+     0,     0,    72,    92,    97,     0,    63,    64,     0,    51,
+     0,    68,     0,     0,     0,     0,    96,    44,    41,    42,
+    45,    89,     0,    16,    39,    10,     0,     0,    79,    80,
+    81,    82,    83,    84,    85,     0,     0,    90,     0,    98,
+    56,     0,     0,    52,    93,     0,    69,    34,    37,    94,
+    95,     0,    15,    17,    75,    77,    73,    65,    97,    66,
+     0,     0,     6,     0,    30,     6,     0,    43,     0,    57,
+     0,     7,     0,    59,     0,    68,     0,     6,    67,    58,
+   104,     0,     0,     0,    46,     0,   105,    53,    60,     0,
+    31,    47,    35,    38,   106,     0,    49,    61,    68,     6,
+     0,     0,     0,     0,    54,    55,     0,    32,    48,    50,
+     6,     0,    33,     0,     0
+};
+
+static const short yydefgoto[] = {     1,
+    31,   143,    32,    60,    61,    34,    50,   146,   169,   181,
+   136,    52,   137,    56,    89,    90,   163,   170,    35,   172,
+   113,   167,   114,    76,    77,   116,    48,    36,   106,    97,
+    98,    37,   158
+};
+
+static const short yypact[] = {-32768,
+   170,   375,   567,-32768,   -25,-32768,    -3,     7,-32768,-32768,
+   -32,   567,-32768,   -29,-32768,   -26,    -7,-32768,-32768,    -5,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,   567,   567,   213,
+-32768,    16,-32768,-32768,-32768,   642,    14,-32768,-32768,    63,
+   597,   567,    -9,-32768,-32768,    18,   567,-32768,   642,    19,
+   567,    20,   567,   567,    15,   537,-32768,   122,   505,     3,
+-32768,-32768,   305,-32768,-32768,   567,   567,   567,   567,   567,
+   567,   567,-32768,-32768,   -18,    21,    26,   642,    39,    -4,
+   410,   567,   419,   567,   428,   466,-32768,-32768,-32768,    36,
+   642,-32768,   259,   505,-32768,-32768,   567,   567,   404,   316,
+   316,    44,    44,    44,    44,   567,   107,-32768,   627,-32768,
+    -8,    79,    45,    43,-32768,    49,   642,-32768,   642,-32768,
+-32768,   537,-32768,-32768,    63,   652,   404,-32768,    38,   642,
+    46,    48,    90,    -1,-32768,    90,    61,-32768,   337,-32768,
+    59,-32768,    65,    64,   103,   567,   505,    90,-32768,-32768,
+   111,    68,    70,    78,    99,   505,-32768,     5,-32768,    75,
+-32768,-32768,-32768,-32768,-32768,    -4,-32768,-32768,   567,    90,
+    13,   213,    81,   505,-32768,-32768,     6,-32768,-32768,-32768,
+    90,   505,-32768,   129,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768,  -135,-32768,   -37,     1,    -2,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,    25,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,   -30,-32768,-32768,  -136,-32768,     0,-32768,-32768,
+-32768,   131,-32768
+};
+
+
+#define        YYLAST          693
+
+
+static const short yytable[] = {    39,
+   147,    33,    40,   111,    43,    93,   144,   165,    93,   154,
+    47,    49,   156,    51,    46,   175,    53,    41,    62,    44,
+    18,    19,    42,    73,    41,    74,    23,    57,    58,   107,
+   166,    27,   173,   112,   174,    54,   145,    55,    42,   131,
+    78,    79,    64,    65,    94,   182,    81,    94,    95,    66,
+    83,   180,    85,    86,   176,    91,    39,    63,    87,   134,
+    80,    82,    84,    96,   108,    99,   100,   101,   102,   103,
+   104,   105,   109,    66,    67,    68,    69,    70,    71,    72,
+    41,   117,   122,   119,    72,   139,   132,   110,   133,   134,
+   135,   124,   142,   123,   140,   141,   125,   126,    67,    68,
+    69,    70,    71,    72,   148,   127,    79,   150,   130,   151,
+   153,   152,     3,   157,     5,     6,   159,   160,     7,   161,
+   162,    91,    11,   168,   178,    64,    65,    16,   185,    17,
+    18,    19,    66,    20,   177,   171,    23,    45,    79,     0,
+     0,    27,     0,    28,   155,   117,   138,     0,     0,    29,
+     0,     0,     0,   164,     0,   128,     0,    67,    68,    69,
+    70,    71,    72,     0,     0,    92,     0,     0,   117,   184,
+     2,   179,    -8,     0,     0,     3,     4,     5,     6,   183,
+     0,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+    16,     0,    17,    18,    19,     0,    20,    21,    22,    23,
+    24,    25,    26,     0,    27,     0,    28,     0,     0,     0,
+     0,    -8,    29,    59,    30,   -12,     0,     0,     3,     4,
+     5,     6,     0,     0,     7,     0,     9,    10,    11,    12,
+    13,    14,    15,    16,     0,    17,    18,    19,     0,    20,
+    21,    22,    23,    24,    25,    26,     0,    27,     0,    28,
+     0,     0,     0,     0,   -12,    29,     0,    30,   -12,    59,
+     0,   -14,     0,     0,     3,     4,     5,     6,     0,     0,
+     7,     0,     9,    10,    11,    12,    13,    14,    15,    16,
+     0,    17,    18,    19,     0,    20,    21,    22,    23,    24,
+    25,    26,     0,    27,     0,    28,     0,     0,     0,     0,
+   -14,    29,     0,    30,   -14,    59,     0,   -11,     0,     0,
+     3,     4,     5,     6,     0,     0,     7,     0,     9,    10,
+    11,    12,    13,    14,    15,    16,     0,    17,    18,    19,
+     0,    20,    21,    22,    23,    24,    25,    26,     0,    27,
+     0,    28,     3,     0,     5,     6,   -11,    29,     7,    30,
+     0,     0,    11,    69,    70,    71,    72,    16,     0,    17,
+    18,    19,     0,    20,     0,     0,    23,     0,     0,     0,
+     0,    27,     0,    28,     0,     0,     0,    38,     0,    29,
+     3,     4,     5,     6,     0,   149,     7,     0,     9,    10,
+    11,    12,    13,    14,    15,    16,     0,    17,    18,    19,
+     0,    20,    21,    22,    23,    24,    25,    26,     0,    27,
+     0,    28,     0,    64,    65,     0,     0,    29,     0,    30,
+    66,     0,    64,    65,     0,     0,     0,     0,     0,    66,
+     0,    64,    65,     0,     0,     0,     0,     0,    66,    67,
+    68,    69,    70,    71,    72,    67,    68,    69,    70,    71,
+    72,     0,     0,   115,    67,    68,    69,    70,    71,    72,
+     0,     0,   118,    67,    68,    69,    70,    71,    72,    64,
+    65,   120,     0,     0,     0,     0,    66,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     0,    67,    68,    69,    70,    71,    72,     0,     0,   121,
+     3,     4,     5,     6,     0,     0,     7,     0,     9,    10,
+    11,    12,    13,    14,    15,    16,     0,    17,    18,    19,
+     0,    20,    21,    22,    23,    24,    25,    26,     0,    27,
+     0,    28,     3,    88,     5,     6,     0,    29,     7,    30,
+     0,     0,    11,     0,     0,     0,     0,    16,     0,    17,
+    18,    19,     0,    20,     0,     0,    23,     0,     0,     0,
+     0,    27,     3,    28,     5,     6,     0,     0,     7,    29,
+     0,     0,    11,     0,     0,     0,     0,    16,     0,    17,
+    18,    19,     0,    20,     0,     0,    23,     0,     0,     0,
+     0,    27,     3,    28,    75,     6,     0,     0,     7,    29,
+     0,     0,    11,     0,     0,     0,     0,    16,     0,    17,
+    18,    19,     0,    20,     0,     0,    23,     0,     0,     0,
+     0,    27,     3,    28,   129,     6,     0,     0,     7,    29,
+     0,     0,    11,     0,     0,    64,    65,    16,     0,    17,
+    18,    19,    66,    20,     0,    64,    23,     0,     0,     0,
+     0,    27,    66,    28,     0,     0,     0,     0,     0,    29,
+     0,     0,     0,     0,     0,     0,     0,    67,    68,    69,
+    70,    71,    72,     0,     0,     0,     0,    67,    68,    69,
+    70,    71,    72
+};
+
+static const short yycheck[] = {     2,
+   136,     1,     3,     8,     8,     3,     8,     3,     3,   146,
+    43,    12,   148,    43,     8,     3,    43,    43,     3,    23,
+    24,    25,    48,    10,    43,    12,    30,    28,    29,    48,
+    26,    35,   169,    38,   170,    43,    38,    43,    48,    48,
+    41,    42,     4,     5,    42,   181,    47,    42,    46,    11,
+    51,    46,    53,    54,    42,    56,    59,    42,    44,    47,
+    43,    43,    43,    63,    44,    66,    67,    68,    69,    70,
+    71,    72,    47,    11,    36,    37,    38,    39,    40,    41,
+    43,    82,    47,    84,    41,    48,     8,    49,    44,    47,
+    42,    94,     3,    93,    49,    48,    97,    98,    36,    37,
+    38,    39,    40,    41,    44,   106,   107,    49,   109,    45,
+     8,    48,     6,     3,     8,     9,    49,    48,    12,    42,
+    22,   122,    16,    49,    44,     4,     5,    21,     0,    23,
+    24,    25,    11,    27,   172,   166,    30,     7,   139,    -1,
+    -1,    35,    -1,    37,   147,   146,   122,    -1,    -1,    43,
+    -1,    -1,    -1,   156,    -1,    49,    -1,    36,    37,    38,
+    39,    40,    41,    -1,    -1,    44,    -1,    -1,   169,     0,
+     1,   174,     3,    -1,    -1,     6,     7,     8,     9,   182,
+    -1,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+    21,    -1,    23,    24,    25,    -1,    27,    28,    29,    30,
+    31,    32,    33,    -1,    35,    -1,    37,    -1,    -1,    -1,
+    -1,    42,    43,     1,    45,     3,    -1,    -1,     6,     7,
+     8,     9,    -1,    -1,    12,    -1,    14,    15,    16,    17,
+    18,    19,    20,    21,    -1,    23,    24,    25,    -1,    27,
+    28,    29,    30,    31,    32,    33,    -1,    35,    -1,    37,
+    -1,    -1,    -1,    -1,    42,    43,    -1,    45,    46,     1,
+    -1,     3,    -1,    -1,     6,     7,     8,     9,    -1,    -1,
+    12,    -1,    14,    15,    16,    17,    18,    19,    20,    21,
+    -1,    23,    24,    25,    -1,    27,    28,    29,    30,    31,
+    32,    33,    -1,    35,    -1,    37,    -1,    -1,    -1,    -1,
+    42,    43,    -1,    45,    46,     1,    -1,     3,    -1,    -1,
+     6,     7,     8,     9,    -1,    -1,    12,    -1,    14,    15,
+    16,    17,    18,    19,    20,    21,    -1,    23,    24,    25,
+    -1,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
+    -1,    37,     6,    -1,     8,     9,    42,    43,    12,    45,
+    -1,    -1,    16,    38,    39,    40,    41,    21,    -1,    23,
+    24,    25,    -1,    27,    -1,    -1,    30,    -1,    -1,    -1,
+    -1,    35,    -1,    37,    -1,    -1,    -1,     3,    -1,    43,
+     6,     7,     8,     9,    -1,    49,    12,    -1,    14,    15,
+    16,    17,    18,    19,    20,    21,    -1,    23,    24,    25,
+    -1,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
+    -1,    37,    -1,     4,     5,    -1,    -1,    43,    -1,    45,
+    11,    -1,     4,     5,    -1,    -1,    -1,    -1,    -1,    11,
+    -1,     4,     5,    -1,    -1,    -1,    -1,    -1,    11,    36,
+    37,    38,    39,    40,    41,    36,    37,    38,    39,    40,
+    41,    -1,    -1,    44,    36,    37,    38,    39,    40,    41,
+    -1,    -1,    44,    36,    37,    38,    39,    40,    41,     4,
+     5,    44,    -1,    -1,    -1,    -1,    11,    -1,    -1,    -1,
+    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+    -1,    36,    37,    38,    39,    40,    41,    -1,    -1,    44,
+     6,     7,     8,     9,    -1,    -1,    12,    -1,    14,    15,
+    16,    17,    18,    19,    20,    21,    -1,    23,    24,    25,
+    -1,    27,    28,    29,    30,    31,    32,    33,    -1,    35,
+    -1,    37,     6,     7,     8,     9,    -1,    43,    12,    45,
+    -1,    -1,    16,    -1,    -1,    -1,    -1,    21,    -1,    23,
+    24,    25,    -1,    27,    -1,    -1,    30,    -1,    -1,    -1,
+    -1,    35,     6,    37,     8,     9,    -1,    -1,    12,    43,
+    -1,    -1,    16,    -1,    -1,    -1,    -1,    21,    -1,    23,
+    24,    25,    -1,    27,    -1,    -1,    30,    -1,    -1,    -1,
+    -1,    35,     6,    37,     8,     9,    -1,    -1,    12,    43,
+    -1,    -1,    16,    -1,    -1,    -1,    -1,    21,    -1,    23,
+    24,    25,    -1,    27,    -1,    -1,    30,    -1,    -1,    -1,
+    -1,    35,     6,    37,     8,     9,    -1,    -1,    12,    43,
+    -1,    -1,    16,    -1,    -1,     4,     5,    21,    -1,    23,
+    24,    25,    11,    27,    -1,     4,    30,    -1,    -1,    -1,
+    -1,    35,    11,    37,    -1,    -1,    -1,    -1,    -1,    43,
+    -1,    -1,    -1,    -1,    -1,    -1,    -1,    36,    37,    38,
+    39,    40,    41,    -1,    -1,    -1,    -1,    36,    37,    38,
+    39,    40,    41
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/gnu/share/bison.simple"
+/* This file comes from bison-1.27.  */
+
+/* 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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, 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
+\f
+/* 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
+\f
+#line 216 "/usr/gnu/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 108 "bc.y"
+{
+                             yyval.i_value = 0;
+                             if (interactive && !quiet)
+                               {
+                                 show_bc_version ();
+                                 welcome ();
+                               }
+                           ;
+    break;}
+case 3:
+#line 119 "bc.y"
+{ run_code (); ;
+    break;}
+case 4:
+#line 121 "bc.y"
+{ run_code (); ;
+    break;}
+case 5:
+#line 123 "bc.y"
+{
+                             yyerrok;
+                             init_gen ();
+                           ;
+    break;}
+case 7:
+#line 130 "bc.y"
+{ warn ("newline not allowed"); ;
+    break;}
+case 8:
+#line 133 "bc.y"
+{ yyval.i_value = 0; ;
+    break;}
+case 12:
+#line 139 "bc.y"
+{ yyval.i_value = 0; ;
+    break;}
+case 19:
+#line 148 "bc.y"
+{ yyval.i_value = yyvsp[0].i_value; ;
+    break;}
+case 20:
+#line 151 "bc.y"
+{ warranty (""); ;
+    break;}
+case 21:
+#line 153 "bc.y"
+{ limits (); ;
+    break;}
+case 22:
+#line 155 "bc.y"
+{
+                             if (yyvsp[0].i_value & 2)
+                               warn ("comparison in expression");
+                             if (yyvsp[0].i_value & 1)
+                               generate ("W");
+                             else 
+                               generate ("p");
+                           ;
+    break;}
+case 23:
+#line 164 "bc.y"
+{
+                             yyval.i_value = 0;
+                             generate ("w");
+                             generate (yyvsp[0].s_value);
+                             free (yyvsp[0].s_value);
+                           ;
+    break;}
+case 24:
+#line 171 "bc.y"
+{
+                             if (break_label == 0)
+                               yyerror ("Break outside a for/while");
+                             else
+                               {
+                                 sprintf (genstr, "J%1d:", break_label);
+                                 generate (genstr);
+                               }
+                           ;
+    break;}
+case 25:
+#line 181 "bc.y"
+{
+                             warn ("Continue statement");
+                             if (continue_label == 0)
+                               yyerror ("Continue outside a for");
+                             else
+                               {
+                                 sprintf (genstr, "J%1d:", continue_label);
+                                 generate (genstr);
+                               }
+                           ;
+    break;}
+case 26:
+#line 192 "bc.y"
+{ exit (0); ;
+    break;}
+case 27:
+#line 194 "bc.y"
+{ generate ("h"); ;
+    break;}
+case 28:
+#line 196 "bc.y"
+{ generate ("R"); ;
+    break;}
+case 29:
+#line 198 "bc.y"
+{
+                             yyvsp[0].i_value = break_label; 
+                             break_label = next_label++;
+                           ;
+    break;}
+case 30:
+#line 203 "bc.y"
+{
+                             if (yyvsp[-1].i_value & 2)
+                               warn ("Comparison in first for expression");
+                             if (yyvsp[-1].i_value >= 0)
+                               generate ("p");
+                             yyvsp[-1].i_value = next_label++;
+                             sprintf (genstr, "N%1d:", yyvsp[-1].i_value);
+                             generate (genstr);
+                           ;
+    break;}
+case 31:
+#line 213 "bc.y"
+{
+                             if (yyvsp[-1].i_value < 0) generate ("1");
+                             yyvsp[-1].i_value = next_label++;
+                             sprintf (genstr, "B%1d:J%1d:", yyvsp[-1].i_value, break_label);
+                             generate (genstr);
+                             yyval.i_value = continue_label;
+                             continue_label = next_label++;
+                             sprintf (genstr, "N%1d:", continue_label);
+                             generate (genstr);
+                           ;
+    break;}
+case 32:
+#line 224 "bc.y"
+{
+                             if (yyvsp[-1].i_value & 2 )
+                               warn ("Comparison in third for expression");
+                             if (yyvsp[-1].i_value & 16)
+                               sprintf (genstr, "J%1d:N%1d:", yyvsp[-7].i_value, yyvsp[-4].i_value);
+                             else
+                               sprintf (genstr, "pJ%1d:N%1d:", yyvsp[-7].i_value, yyvsp[-4].i_value);
+                             generate (genstr);
+                           ;
+    break;}
+case 33:
+#line 234 "bc.y"
+{
+                             sprintf (genstr, "J%1d:N%1d:",
+                                      continue_label, break_label);
+                             generate (genstr);
+                             break_label = yyvsp[-13].i_value;
+                             continue_label = yyvsp[-5].i_value;
+                           ;
+    break;}
+case 34:
+#line 242 "bc.y"
+{
+                             yyvsp[-1].i_value = if_label;
+                             if_label = next_label++;
+                             sprintf (genstr, "Z%1d:", if_label);
+                             generate (genstr);
+                           ;
+    break;}
+case 35:
+#line 249 "bc.y"
+{
+                             sprintf (genstr, "N%1d:", if_label); 
+                             generate (genstr);
+                             if_label = yyvsp[-5].i_value;
+                           ;
+    break;}
+case 36:
+#line 255 "bc.y"
+{
+                             yyvsp[0].i_value = next_label++;
+                             sprintf (genstr, "N%1d:", yyvsp[0].i_value);
+                             generate (genstr);
+                           ;
+    break;}
+case 37:
+#line 261 "bc.y"
+{
+                             yyvsp[0].i_value = break_label; 
+                             break_label = next_label++;
+                             sprintf (genstr, "Z%1d:", break_label);
+                             generate (genstr);
+                           ;
+    break;}
+case 38:
+#line 268 "bc.y"
+{
+                             sprintf (genstr, "J%1d:N%1d:", yyvsp[-7].i_value, break_label);
+                             generate (genstr);
+                             break_label = yyvsp[-4].i_value;
+                           ;
+    break;}
+case 39:
+#line 274 "bc.y"
+{ yyval.i_value = 0; ;
+    break;}
+case 40:
+#line 276 "bc.y"
+{  warn ("print statement"); ;
+    break;}
+case 44:
+#line 283 "bc.y"
+{
+                             generate ("O");
+                             generate (yyvsp[0].s_value);
+                             free (yyvsp[0].s_value);
+                           ;
+    break;}
+case 45:
+#line 289 "bc.y"
+{ generate ("P"); ;
+    break;}
+case 47:
+#line 293 "bc.y"
+{
+                             warn ("else clause in if statement");
+                             yyvsp[0].i_value = next_label++;
+                             sprintf (genstr, "J%d:N%1d:", yyvsp[0].i_value, if_label); 
+                             generate (genstr);
+                             if_label = yyvsp[0].i_value;
+                           ;
+    break;}
+case 49:
+#line 303 "bc.y"
+{
+                             /* Check auto list against parameter list? */
+                             check_params (yyvsp[-5].a_value,yyvsp[0].a_value);
+                             sprintf (genstr, "F%d,%s.%s[",
+                                      lookup(yyvsp[-7].s_value,FUNCTDEF), 
+                                      arg_str (yyvsp[-5].a_value), arg_str (yyvsp[0].a_value));
+                             generate (genstr);
+                             free_args (yyvsp[-5].a_value);
+                             free_args (yyvsp[0].a_value);
+                             yyvsp[-8].i_value = next_label;
+                             next_label = 1;
+                           ;
+    break;}
+case 50:
+#line 316 "bc.y"
+{
+                             generate ("0R]");
+                             next_label = yyvsp[-11].i_value;
+                           ;
+    break;}
+case 51:
+#line 322 "bc.y"
+{ yyval.a_value = NULL; ;
+    break;}
+case 53:
+#line 326 "bc.y"
+{ yyval.a_value = NULL; ;
+    break;}
+case 54:
+#line 328 "bc.y"
+{ yyval.a_value = yyvsp[-1].a_value; ;
+    break;}
+case 55:
+#line 330 "bc.y"
+{ yyval.a_value = yyvsp[-1].a_value; ;
+    break;}
+case 56:
+#line 333 "bc.y"
+{ yyval.a_value = nextarg (NULL, lookup (yyvsp[0].s_value,SIMPLE), FALSE);;
+    break;}
+case 57:
+#line 335 "bc.y"
+{ yyval.a_value = nextarg (NULL, lookup (yyvsp[-2].s_value,ARRAY), FALSE); ;
+    break;}
+case 58:
+#line 337 "bc.y"
+{ yyval.a_value = nextarg (NULL, lookup (yyvsp[-2].s_value,ARRAY), TRUE); ;
+    break;}
+case 59:
+#line 339 "bc.y"
+{ yyval.a_value = nextarg (yyvsp[-2].a_value, lookup (yyvsp[0].s_value,SIMPLE), FALSE); ;
+    break;}
+case 60:
+#line 341 "bc.y"
+{ yyval.a_value = nextarg (yyvsp[-4].a_value, lookup (yyvsp[-2].s_value,ARRAY), FALSE); ;
+    break;}
+case 61:
+#line 343 "bc.y"
+{ yyval.a_value = nextarg (yyvsp[-5].a_value, lookup (yyvsp[-2].s_value,ARRAY), TRUE); ;
+    break;}
+case 62:
+#line 346 "bc.y"
+{ yyval.a_value = NULL; ;
+    break;}
+case 64:
+#line 350 "bc.y"
+{
+                             if (yyvsp[0].i_value & 2) warn ("comparison in argument");
+                             yyval.a_value = nextarg (NULL,0,FALSE);
+                           ;
+    break;}
+case 65:
+#line 355 "bc.y"
+{
+                             sprintf (genstr, "K%d:", -lookup (yyvsp[-2].s_value,ARRAY));
+                             generate (genstr);
+                             yyval.a_value = nextarg (NULL,1,FALSE);
+                           ;
+    break;}
+case 66:
+#line 361 "bc.y"
+{
+                             if (yyvsp[0].i_value & 2) warn ("comparison in argument");
+                             yyval.a_value = nextarg (yyvsp[-2].a_value,0,FALSE);
+                           ;
+    break;}
+case 67:
+#line 366 "bc.y"
+{
+                             sprintf (genstr, "K%d:", -lookup (yyvsp[-2].s_value,ARRAY));
+                             generate (genstr);
+                             yyval.a_value = nextarg (yyvsp[-4].a_value,1,FALSE);
+                           ;
+    break;}
+case 68:
+#line 382 "bc.y"
+{
+                             yyval.i_value = 16;
+                             warn ("Missing expression in for statement");
+                           ;
+    break;}
+case 70:
+#line 389 "bc.y"
+{
+                             yyval.i_value = 0;
+                             generate ("0");
+                           ;
+    break;}
+case 71:
+#line 394 "bc.y"
+{
+                             if (yyvsp[0].i_value & 2)
+                               warn ("comparison in return expresion");
+                             if (!(yyvsp[0].i_value & 4))
+                               warn ("return expression requires parenthesis");
+                           ;
+    break;}
+case 72:
+#line 402 "bc.y"
+{
+                             if (yyvsp[0].c_value != '=')
+                               {
+                                 if (yyvsp[-1].i_value < 0)
+                                   sprintf (genstr, "DL%d:", -yyvsp[-1].i_value);
+                                 else
+                                   sprintf (genstr, "l%d:", yyvsp[-1].i_value);
+                                 generate (genstr);
+                               }
+                           ;
+    break;}
+case 73:
+#line 413 "bc.y"
+{
+                             if (yyvsp[0].i_value & 2) warn("comparison in assignment");
+                             if (yyvsp[-2].c_value != '=')
+                               {
+                                 sprintf (genstr, "%c", yyvsp[-2].c_value);
+                                 generate (genstr);
+                               }
+                             if (yyvsp[-3].i_value < 0)
+                               sprintf (genstr, "S%d:", -yyvsp[-3].i_value);
+                             else
+                               sprintf (genstr, "s%d:", yyvsp[-3].i_value);
+                             generate (genstr);
+                             yyval.i_value = 0;
+                           ;
+    break;}
+case 74:
+#line 429 "bc.y"
+{
+                             warn("&& operator");
+                             yyvsp[0].i_value = next_label++;
+                             sprintf (genstr, "DZ%d:p", yyvsp[0].i_value);
+                             generate (genstr);
+                           ;
+    break;}
+case 75:
+#line 436 "bc.y"
+{
+                             sprintf (genstr, "DZ%d:p1N%d:", yyvsp[-2].i_value, yyvsp[-2].i_value);
+                             generate (genstr);
+                             yyval.i_value = (yyvsp[-3].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 76:
+#line 442 "bc.y"
+{
+                             warn("|| operator");
+                             yyvsp[0].i_value = next_label++;
+                             sprintf (genstr, "B%d:", yyvsp[0].i_value);
+                             generate (genstr);
+                           ;
+    break;}
+case 77:
+#line 449 "bc.y"
+{
+                             int tmplab;
+                             tmplab = next_label++;
+                             sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
+                                      yyvsp[-2].i_value, tmplab, yyvsp[-2].i_value, tmplab);
+                             generate (genstr);
+                             yyval.i_value = (yyvsp[-3].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 78:
+#line 458 "bc.y"
+{
+                             yyval.i_value = yyvsp[0].i_value & ~4;
+                             warn("! operator");
+                             generate ("!");
+                           ;
+    break;}
+case 79:
+#line 464 "bc.y"
+{
+                             yyval.i_value = 3;
+                             switch (*(yyvsp[-1].s_value))
+                               {
+                               case '=':
+                                 generate ("=");
+                                 break;
+
+                               case '!':
+                                 generate ("#");
+                                 break;
+
+                               case '<':
+                                 if (yyvsp[-1].s_value[1] == '=')
+                                   generate ("{");
+                                 else
+                                   generate ("<");
+                                 break;
+
+                               case '>':
+                                 if (yyvsp[-1].s_value[1] == '=')
+                                   generate ("}");
+                                 else
+                                   generate (">");
+                                 break;
+                               }
+                           ;
+    break;}
+case 80:
+#line 492 "bc.y"
+{
+                             generate ("+");
+                             yyval.i_value = (yyvsp[-2].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 81:
+#line 497 "bc.y"
+{
+                             generate ("-");
+                             yyval.i_value = (yyvsp[-2].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 82:
+#line 502 "bc.y"
+{
+                             generate ("*");
+                             yyval.i_value = (yyvsp[-2].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 83:
+#line 507 "bc.y"
+{
+                             generate ("/");
+                             yyval.i_value = (yyvsp[-2].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 84:
+#line 512 "bc.y"
+{
+                             generate ("%");
+                             yyval.i_value = (yyvsp[-2].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 85:
+#line 517 "bc.y"
+{
+                             generate ("^");
+                             yyval.i_value = (yyvsp[-2].i_value | yyvsp[0].i_value) & ~4;
+                           ;
+    break;}
+case 86:
+#line 522 "bc.y"
+{
+                             generate ("n");
+                             yyval.i_value = yyvsp[0].i_value & ~4;
+                           ;
+    break;}
+case 87:
+#line 527 "bc.y"
+{
+                             yyval.i_value = 1;
+                             if (yyvsp[0].i_value < 0)
+                               sprintf (genstr, "L%d:", -yyvsp[0].i_value);
+                             else
+                               sprintf (genstr, "l%d:", yyvsp[0].i_value);
+                             generate (genstr);
+                           ;
+    break;}
+case 88:
+#line 536 "bc.y"
+{
+                             int len = strlen(yyvsp[0].s_value);
+                             yyval.i_value = 1;
+                             if (len == 1 && *yyvsp[0].s_value == '0')
+                               generate ("0");
+                             else if (len == 1 && *yyvsp[0].s_value == '1')
+                               generate ("1");
+                             else
+                               {
+                                 generate ("K");
+                                 generate (yyvsp[0].s_value);
+                                 generate (":");
+                               }
+                             free (yyvsp[0].s_value);
+                           ;
+    break;}
+case 89:
+#line 552 "bc.y"
+{ yyval.i_value = yyvsp[-1].i_value | 5; ;
+    break;}
+case 90:
+#line 554 "bc.y"
+{
+                             yyval.i_value = 1;
+                             if (yyvsp[-1].a_value != NULL)
+                               { 
+                                 sprintf (genstr, "C%d,%s:",
+                                          lookup (yyvsp[-3].s_value,FUNCT),
+                                          call_str (yyvsp[-1].a_value));
+                                 free_args (yyvsp[-1].a_value);
+                               }
+                             else
+                               {
+                                 sprintf (genstr, "C%d:", lookup (yyvsp[-3].s_value,FUNCT));
+                               }
+                             generate (genstr);
+                           ;
+    break;}
+case 91:
+#line 570 "bc.y"
+{
+                             yyval.i_value = 1;
+                             if (yyvsp[0].i_value < 0)
+                               {
+                                 if (yyvsp[-1].c_value == '+')
+                                   sprintf (genstr, "DA%d:L%d:", -yyvsp[0].i_value, -yyvsp[0].i_value);
+                                 else
+                                   sprintf (genstr, "DM%d:L%d:", -yyvsp[0].i_value, -yyvsp[0].i_value);
+                               }
+                             else
+                               {
+                                 if (yyvsp[-1].c_value == '+')
+                                   sprintf (genstr, "i%d:l%d:", yyvsp[0].i_value, yyvsp[0].i_value);
+                                 else
+                                   sprintf (genstr, "d%d:l%d:", yyvsp[0].i_value, yyvsp[0].i_value);
+                               }
+                             generate (genstr);
+                           ;
+    break;}
+case 92:
+#line 589 "bc.y"
+{
+                             yyval.i_value = 1;
+                             if (yyvsp[-1].i_value < 0)
+                               {
+                                 sprintf (genstr, "DL%d:x", -yyvsp[-1].i_value);
+                                 generate (genstr); 
+                                 if (yyvsp[0].c_value == '+')
+                                   sprintf (genstr, "A%d:", -yyvsp[-1].i_value);
+                                 else
+                                     sprintf (genstr, "M%d:", -yyvsp[-1].i_value);
+                               }
+                             else
+                               {
+                                 sprintf (genstr, "l%d:", yyvsp[-1].i_value);
+                                 generate (genstr);
+                                 if (yyvsp[0].c_value == '+')
+                                   sprintf (genstr, "i%d:", yyvsp[-1].i_value);
+                                 else
+                                   sprintf (genstr, "d%d:", yyvsp[-1].i_value);
+                               }
+                             generate (genstr);
+                           ;
+    break;}
+case 93:
+#line 612 "bc.y"
+{ generate ("cL"); yyval.i_value = 1;;
+    break;}
+case 94:
+#line 614 "bc.y"
+{ generate ("cR"); yyval.i_value = 1;;
+    break;}
+case 95:
+#line 616 "bc.y"
+{ generate ("cS"); yyval.i_value = 1;;
+    break;}
+case 96:
+#line 618 "bc.y"
+{
+                             warn ("read function");
+                             generate ("cI"); yyval.i_value = 1;
+                           ;
+    break;}
+case 97:
+#line 624 "bc.y"
+{ yyval.i_value = lookup(yyvsp[0].s_value,SIMPLE); ;
+    break;}
+case 98:
+#line 626 "bc.y"
+{
+                             if (yyvsp[-1].i_value > 1) warn("comparison in subscript");
+                             yyval.i_value = lookup(yyvsp[-3].s_value,ARRAY);
+                           ;
+    break;}
+case 99:
+#line 631 "bc.y"
+{ yyval.i_value = 0; ;
+    break;}
+case 100:
+#line 633 "bc.y"
+{ yyval.i_value = 1; ;
+    break;}
+case 101:
+#line 635 "bc.y"
+{ yyval.i_value = 2; ;
+    break;}
+case 102:
+#line 637 "bc.y"
+{ yyval.i_value = 3;
+                             warn ("History variable");
+                           ;
+    break;}
+case 103:
+#line 641 "bc.y"
+{ yyval.i_value = 4;
+                             warn ("Last variable");
+                           ;
+    break;}
+case 104:
+#line 647 "bc.y"
+{ warn ("End of line required"); ;
+    break;}
+case 106:
+#line 650 "bc.y"
+{ warn ("Too many end of lines"); ;
+    break;}
+}
+   /* the action file gets copied in in place of this dollarsign */
+#line 542 "/usr/gnu/share/bison.simple"
+\f
+  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 653 "bc.y"
+
+
diff --git a/bc/bc.h b/bc/bc.h
new file mode 100644 (file)
index 0000000..4a1f59e
--- /dev/null
+++ b/bc/bc.h
@@ -0,0 +1,42 @@
+typedef union {
+       char     *s_value;
+       char      c_value;
+       int       i_value;
+       arg_list *a_value;
+       } YYSTYPE;
+#define        ENDOFLINE       257
+#define        AND     258
+#define        OR      259
+#define        NOT     260
+#define        STRING  261
+#define        NAME    262
+#define        NUMBER  263
+#define        ASSIGN_OP       264
+#define        REL_OP  265
+#define        INCR_DECR       266
+#define        Define  267
+#define        Break   268
+#define        Quit    269
+#define        Length  270
+#define        Return  271
+#define        For     272
+#define        If      273
+#define        While   274
+#define        Sqrt    275
+#define        Else    276
+#define        Scale   277
+#define        Ibase   278
+#define        Obase   279
+#define        Auto    280
+#define        Read    281
+#define        Warranty        282
+#define        Halt    283
+#define        Last    284
+#define        Continue        285
+#define        Print   286
+#define        Limits  287
+#define        UNARY_MINUS     288
+#define        HistoryVar      289
+
+
+extern YYSTYPE yylval;
diff --git a/bc/bc.y b/bc/bc.y
new file mode 100644 (file)
index 0000000..c538eec
--- /dev/null
+++ b/bc/bc.y
@@ -0,0 +1,654 @@
+%{
+/* bc.y: The grammar for a POSIX compatable bc processor with some
+         extensions to the language. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to:
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+%}
+
+%start program
+
+%union {
+       char     *s_value;
+       char      c_value;
+       int       i_value;
+       arg_list *a_value;
+       }
+
+/* Extensions over POSIX bc.
+   a) NAME was LETTER.  This grammar allows longer names.
+      Single letter names will still work.
+   b) Relational_expression allowed only one comparison.
+      This grammar has added boolean expressions with
+      && (and) || (or) and ! (not) and allowed all of them in
+      full expressions.
+   c) Added an else to the if.
+   d) Call by variable array parameters
+   e) read() procedure that reads a number under program control from stdin.
+   f) halt statement that halts the the program under program control.  It
+      is an executed statement.
+   g) continue statement for for loops.
+   h) optional expressions in the for loop.
+   i) print statement to print multiple numbers per line.
+   j) warranty statement to print an extended warranty notice.
+   j) limits statement to print the processor's limits.
+*/
+
+%token <i_value> ENDOFLINE AND OR NOT
+%token <s_value> STRING NAME NUMBER
+/*     '-', '+' are tokens themselves          */
+/*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
+%token <c_value> ASSIGN_OP
+/*     '==', '<=', '>=', '!=', '<', '>'        */
+%token <s_value> REL_OP
+/*     '++', '--'                              */
+%token <c_value> INCR_DECR
+/*     'define', 'break', 'quit', 'length'     */
+%token <i_value> Define    Break    Quit    Length
+/*     'return', 'for', 'if', 'while', 'sqrt', 'else'  */
+%token <i_value> Return    For    If    While    Sqrt   Else
+/*     'scale', 'ibase', 'obase', 'auto', 'read'       */
+%token <i_value> Scale    Ibase    Obase    Auto  Read
+/*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'   */
+%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
+/*     'history' */
+%token <i_value> UNARY_MINUS HistoryVar
+
+/* Types of all other things. */
+%type <i_value> expression return_expression named_expression opt_expression
+%type <c_value> '+' '-' '*' '/' '%' 
+%type <a_value> opt_parameter_list opt_auto_define_list define_list
+%type <a_value> opt_argument_list argument_list
+%type <i_value> program input_item semicolon_list statement_list
+%type <i_value> statement function statement_or_error required_eol
+
+/* precedence */
+%left OR
+%left AND
+%nonassoc NOT
+%left REL_OP
+%right ASSIGN_OP
+%left '+' '-'
+%left '*' '/' '%'
+%right '^'
+%nonassoc UNARY_MINUS
+%nonassoc INCR_DECR
+
+%%
+program                        : /* empty */
+                           {
+                             $$ = 0;
+                             if (interactive && !quiet)
+                               {
+                                 show_bc_version ();
+                                 welcome ();
+                               }
+                           }
+                       | program input_item
+                       ;
+input_item             : semicolon_list ENDOFLINE
+                           { run_code (); }
+                       | function
+                           { run_code (); }
+                       | error ENDOFLINE
+                           {
+                             yyerrok;
+                             init_gen ();
+                           }
+                       ;
+opt_newline            : /* empty */
+                       | ENDOFLINE
+                           { warn ("newline not allowed"); }
+                       ;
+semicolon_list         : /* empty */
+                           { $$ = 0; }
+                       | statement_or_error
+                       | semicolon_list ';' statement_or_error
+                       | semicolon_list ';'
+                       ;
+statement_list         : /* empty */
+                           { $$ = 0; }
+                       | statement_or_error
+                       | statement_list ENDOFLINE
+                       | statement_list ENDOFLINE statement_or_error
+                       | statement_list ';'
+                       | statement_list ';' statement
+                       ;
+statement_or_error     : statement
+                       | error statement
+                           { $$ = $2; }
+                       ;
+statement              : Warranty
+                           { warranty (""); }
+                       | Limits
+                           { limits (); }
+                       | expression
+                           {
+                             if ($1 & 2)
+                               warn ("comparison in expression");
+                             if ($1 & 1)
+                               generate ("W");
+                             else 
+                               generate ("p");
+                           }
+                       | STRING
+                           {
+                             $$ = 0;
+                             generate ("w");
+                             generate ($1);
+                             free ($1);
+                           }
+                       | Break
+                           {
+                             if (break_label == 0)
+                               yyerror ("Break outside a for/while");
+                             else
+                               {
+                                 sprintf (genstr, "J%1d:", break_label);
+                                 generate (genstr);
+                               }
+                           }
+                       | Continue
+                           {
+                             warn ("Continue statement");
+                             if (continue_label == 0)
+                               yyerror ("Continue outside a for");
+                             else
+                               {
+                                 sprintf (genstr, "J%1d:", continue_label);
+                                 generate (genstr);
+                               }
+                           }
+                       | Quit
+                           { exit (0); }
+                       | Halt
+                           { generate ("h"); }
+                       | Return return_expression
+                           { generate ("R"); }
+                       | For 
+                           {
+                             $1 = break_label; 
+                             break_label = next_label++;
+                           }
+                         '(' opt_expression ';'
+                           {
+                             if ($4 & 2)
+                               warn ("Comparison in first for expression");
+                             if (!($4 & 16))
+                               generate ("p");
+                             $4 = next_label++;
+                             sprintf (genstr, "N%1d:", $4);
+                             generate (genstr);
+                           }
+                         opt_expression ';'
+                           {
+                             if ($7 & 16) generate ("1");
+                             $7 = next_label++;
+                             sprintf (genstr, "B%1d:J%1d:", $7, break_label);
+                             generate (genstr);
+                             $<i_value>$ = continue_label;
+                             continue_label = next_label++;
+                             sprintf (genstr, "N%1d:", continue_label);
+                             generate (genstr);
+                           }
+                         opt_expression ')'
+                           {
+                             if ($10 & 2 )
+                               warn ("Comparison in third for expression");
+                             if ($10 & 16)
+                               sprintf (genstr, "J%1d:N%1d:", $4, $7);
+                             else
+                               sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
+                             generate (genstr);
+                           }
+                         opt_newline statement
+                           {
+                             sprintf (genstr, "J%1d:N%1d:",
+                                      continue_label, break_label);
+                             generate (genstr);
+                             break_label = $1;
+                             continue_label = $<i_value>9;
+                           }
+                       | If '(' expression ')' 
+                           {
+                             $3 = if_label;
+                             if_label = next_label++;
+                             sprintf (genstr, "Z%1d:", if_label);
+                             generate (genstr);
+                           }
+                         opt_newline statement  opt_else
+                           {
+                             sprintf (genstr, "N%1d:", if_label); 
+                             generate (genstr);
+                             if_label = $3;
+                           }
+                       | While 
+                           {
+                             $1 = next_label++;
+                             sprintf (genstr, "N%1d:", $1);
+                             generate (genstr);
+                           }
+                       '(' expression 
+                           {
+                             $4 = break_label; 
+                             break_label = next_label++;
+                             sprintf (genstr, "Z%1d:", break_label);
+                             generate (genstr);
+                           }
+                       ')' opt_newline statement
+                           {
+                             sprintf (genstr, "J%1d:N%1d:", $1, break_label);
+                             generate (genstr);
+                             break_label = $4;
+                           }
+                       | '{' statement_list '}'
+                           { $$ = 0; }
+                       | Print
+                           {  warn ("print statement"); }
+                         print_list
+                       ;
+print_list             : print_element
+                       | print_element ',' print_list
+                       ;
+print_element          : STRING
+                           {
+                             generate ("O");
+                             generate ($1);
+                             free ($1);
+                           }
+                       | expression
+                           { generate ("P"); }
+                       ;
+opt_else               : /* nothing */
+                       | Else 
+                           {
+                             warn ("else clause in if statement");
+                             $1 = next_label++;
+                             sprintf (genstr, "J%d:N%1d:", $1, if_label); 
+                             generate (genstr);
+                             if_label = $1;
+                           }
+                         opt_newline statement
+function               : Define NAME '(' opt_parameter_list ')' opt_newline
+                         '{' required_eol opt_auto_define_list 
+                           {
+                             /* Check auto list against parameter list? */
+                             check_params ($4,$9);
+                             sprintf (genstr, "F%d,%s.%s[",
+                                      lookup($2,FUNCTDEF), 
+                                      arg_str ($4), arg_str ($9));
+                             generate (genstr);
+                             free_args ($4);
+                             free_args ($9);
+                             $1 = next_label;
+                             next_label = 1;
+                           }
+                         statement_list /* ENDOFLINE */ '}'
+                           {
+                             generate ("0R]");
+                             next_label = $1;
+                           }
+                       ;
+opt_parameter_list     : /* empty */ 
+                           { $$ = NULL; }
+                       | define_list
+                       ;
+opt_auto_define_list   : /* empty */ 
+                           { $$ = NULL; }
+                       | Auto define_list ENDOFLINE
+                           { $$ = $2; } 
+                       | Auto define_list ';'
+                           { $$ = $2; } 
+                       ;
+define_list            : NAME
+                           { $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE);}
+                       | NAME '[' ']'
+                           { $$ = nextarg (NULL, lookup ($1,ARRAY), FALSE); }
+                       | '*' NAME '[' ']'
+                           { $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE); }
+                       | define_list ',' NAME
+                           { $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
+                       | define_list ',' NAME '[' ']'
+                           { $$ = nextarg ($1, lookup ($3,ARRAY), FALSE); }
+                       | define_list ',' '*' NAME '[' ']'
+                           { $$ = nextarg ($1, lookup ($4,ARRAY), TRUE); }
+                       ;
+opt_argument_list      : /* empty */
+                           { $$ = NULL; }
+                       | argument_list
+                       ;
+argument_list          : expression
+                           {
+                             if ($1 & 2) warn ("comparison in argument");
+                             $$ = nextarg (NULL,0,FALSE);
+                           }
+                       | NAME '[' ']'
+                           {
+                             sprintf (genstr, "K%d:", -lookup ($1,ARRAY));
+                             generate (genstr);
+                             $$ = nextarg (NULL,1,FALSE);
+                           }
+                       | argument_list ',' expression
+                           {
+                             if ($3 & 2) warn ("comparison in argument");
+                             $$ = nextarg ($1,0,FALSE);
+                           }
+                       | argument_list ',' NAME '[' ']'
+                           {
+                             sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
+                             generate (genstr);
+                             $$ = nextarg ($1,1,FALSE);
+                           }
+                       ;
+
+/* Expression lval meanings!  (Bits mean something!)
+ *  0 => Top op is assignment.
+ *  1 => Top op is not assignment.
+ *  2 => Comparison is somewhere in expression.
+ *  4 => Expression is in parenthesis.
+ * 16 => Empty optional expression.
+ */
+
+opt_expression                 : /* empty */
+                           {
+                             $$ = 16;
+                             warn ("Missing expression in for statement");
+                           }
+                       | expression
+                       ;
+return_expression      : /* empty */
+                           {
+                             $$ = 0;
+                             generate ("0");
+                           }
+                       | expression
+                           {
+                             if ($1 & 2)
+                               warn ("comparison in return expresion");
+                             if (!($1 & 4))
+                               warn ("return expression requires parenthesis");
+                           }
+                       ;
+expression             :  named_expression ASSIGN_OP 
+                           {
+                             if ($2 != '=')
+                               {
+                                 if ($1 < 0)
+                                   sprintf (genstr, "DL%d:", -$1);
+                                 else
+                                   sprintf (genstr, "l%d:", $1);
+                                 generate (genstr);
+                               }
+                           }
+                         expression
+                           {
+                             if ($4 & 2) warn("comparison in assignment");
+                             if ($2 != '=')
+                               {
+                                 sprintf (genstr, "%c", $2);
+                                 generate (genstr);
+                               }
+                             if ($1 < 0)
+                               sprintf (genstr, "S%d:", -$1);
+                             else
+                               sprintf (genstr, "s%d:", $1);
+                             generate (genstr);
+                             $$ = 0;
+                           }
+                       ;
+                       | expression AND 
+                           {
+                             warn("&& operator");
+                             $2 = next_label++;
+                             sprintf (genstr, "DZ%d:p", $2);
+                             generate (genstr);
+                           }
+                         expression
+                           {
+                             sprintf (genstr, "DZ%d:p1N%d:", $2, $2);
+                             generate (genstr);
+                             $$ = ($1 | $4) & ~4;
+                           }
+                       | expression OR
+                           {
+                             warn("|| operator");
+                             $2 = next_label++;
+                             sprintf (genstr, "B%d:", $2);
+                             generate (genstr);
+                           }
+                         expression
+                           {
+                             int tmplab;
+                             tmplab = next_label++;
+                             sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
+                                      $2, tmplab, $2, tmplab);
+                             generate (genstr);
+                             $$ = ($1 | $4) & ~4;
+                           }
+                       | NOT expression
+                           {
+                             $$ = $2 & ~4;
+                             warn("! operator");
+                             generate ("!");
+                           }
+                       | expression REL_OP expression
+                           {
+                             $$ = 3;
+                             switch (*($2))
+                               {
+                               case '=':
+                                 generate ("=");
+                                 break;
+
+                               case '!':
+                                 generate ("#");
+                                 break;
+
+                               case '<':
+                                 if ($2[1] == '=')
+                                   generate ("{");
+                                 else
+                                   generate ("<");
+                                 break;
+
+                               case '>':
+                                 if ($2[1] == '=')
+                                   generate ("}");
+                                 else
+                                   generate (">");
+                                 break;
+                               }
+                           }
+                       | expression '+' expression
+                           {
+                             generate ("+");
+                             $$ = ($1 | $3) & ~4;
+                           }
+                       | expression '-' expression
+                           {
+                             generate ("-");
+                             $$ = ($1 | $3) & ~4;
+                           }
+                       | expression '*' expression
+                           {
+                             generate ("*");
+                             $$ = ($1 | $3) & ~4;
+                           }
+                       | expression '/' expression
+                           {
+                             generate ("/");
+                             $$ = ($1 | $3) & ~4;
+                           }
+                       | expression '%' expression
+                           {
+                             generate ("%");
+                             $$ = ($1 | $3) & ~4;
+                           }
+                       | expression '^' expression
+                           {
+                             generate ("^");
+                             $$ = ($1 | $3) & ~4;
+                           }
+                       | '-' expression  %prec UNARY_MINUS
+                           {
+                             generate ("n");
+                             $$ = $2 & ~4;
+                           }
+                       | named_expression
+                           {
+                             $$ = 1;
+                             if ($1 < 0)
+                               sprintf (genstr, "L%d:", -$1);
+                             else
+                               sprintf (genstr, "l%d:", $1);
+                             generate (genstr);
+                           }
+                       | NUMBER
+                           {
+                             int len = strlen($1);
+                             $$ = 1;
+                             if (len == 1 && *$1 == '0')
+                               generate ("0");
+                             else if (len == 1 && *$1 == '1')
+                               generate ("1");
+                             else
+                               {
+                                 generate ("K");
+                                 generate ($1);
+                                 generate (":");
+                               }
+                             free ($1);
+                           }
+                       | '(' expression ')'
+                           { $$ = $2 | 5; }
+                       | NAME '(' opt_argument_list ')'
+                           {
+                             $$ = 1;
+                             if ($3 != NULL)
+                               { 
+                                 sprintf (genstr, "C%d,%s:",
+                                          lookup ($1,FUNCT),
+                                          call_str ($3));
+                                 free_args ($3);
+                               }
+                             else
+                               {
+                                 sprintf (genstr, "C%d:", lookup ($1,FUNCT));
+                               }
+                             generate (genstr);
+                           }
+                       | INCR_DECR named_expression
+                           {
+                             $$ = 1;
+                             if ($2 < 0)
+                               {
+                                 if ($1 == '+')
+                                   sprintf (genstr, "DA%d:L%d:", -$2, -$2);
+                                 else
+                                   sprintf (genstr, "DM%d:L%d:", -$2, -$2);
+                               }
+                             else
+                               {
+                                 if ($1 == '+')
+                                   sprintf (genstr, "i%d:l%d:", $2, $2);
+                                 else
+                                   sprintf (genstr, "d%d:l%d:", $2, $2);
+                               }
+                             generate (genstr);
+                           }
+                       | named_expression INCR_DECR
+                           {
+                             $$ = 1;
+                             if ($1 < 0)
+                               {
+                                 sprintf (genstr, "DL%d:x", -$1);
+                                 generate (genstr); 
+                                 if ($2 == '+')
+                                   sprintf (genstr, "A%d:", -$1);
+                                 else
+                                     sprintf (genstr, "M%d:", -$1);
+                               }
+                             else
+                               {
+                                 sprintf (genstr, "l%d:", $1);
+                                 generate (genstr);
+                                 if ($2 == '+')
+                                   sprintf (genstr, "i%d:", $1);
+                                 else
+                                   sprintf (genstr, "d%d:", $1);
+                               }
+                             generate (genstr);
+                           }
+                       | Length '(' expression ')'
+                           { generate ("cL"); $$ = 1;}
+                       | Sqrt '(' expression ')'
+                           { generate ("cR"); $$ = 1;}
+                       | Scale '(' expression ')'
+                           { generate ("cS"); $$ = 1;}
+                       | Read '(' ')'
+                           {
+                             warn ("read function");
+                             generate ("cI"); $$ = 1;
+                           }
+                       ;
+named_expression       : NAME
+                           { $$ = lookup($1,SIMPLE); }
+                       | NAME '[' expression ']'
+                           {
+                             if ($3 > 1) warn("comparison in subscript");
+                             $$ = lookup($1,ARRAY);
+                           }
+                       | Ibase
+                           { $$ = 0; }
+                       | Obase
+                           { $$ = 1; }
+                       | Scale
+                           { $$ = 2; }
+                       | HistoryVar
+                           { $$ = 3;
+                             warn ("History variable");
+                           }
+                       | Last
+                           { $$ = 4;
+                             warn ("Last variable");
+                           }
+                       ;
+
+
+required_eol           : { warn ("End of line required"); }
+                       | ENDOFLINE
+                       | required_eol ENDOFLINE
+                         { warn ("Too many end of lines"); }
+                       ;
+
+%%
+
diff --git a/bc/bcdefs.h b/bc/bcdefs.h
new file mode 100644 (file)
index 0000000..260cd12
--- /dev/null
@@ -0,0 +1,188 @@
+/* bcdefs.h:  The single file to include all constants and type definitions. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+/* Include the configuration file. */
+#include "config.h"
+
+/* Standard includes for all files. */
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#if defined(LIBEDIT)
+#include <histedit.h>
+#endif
+
+#if defined(READLINE)
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+/* Include the other definitions. */
+#include "const.h"
+#include "number.h"
+
+/* These definitions define all the structures used in
+   code and data storage.  This includes the representation of
+   labels.   The "guiding" principle is to make structures that
+   take a minimum of space when unused but can be built to contain
+   the full structures.  */
+
+/* Labels are first.  Labels are generated sequentially in functions
+   and full code.  They just "point" to a single bye in the code.  The
+   "address" is the byte number.  The byte number is used to get an
+   actual character pointer. */
+
+typedef struct bc_label_group
+    {
+      long l_adrs [ BC_LABEL_GROUP ];
+      struct bc_label_group *l_next;
+    } bc_label_group;
+
+/* Argument list.  Recorded in the function so arguments can
+   be checked at call time. */
+
+typedef struct arg_list
+    {
+      int av_name;
+      int arg_is_var;          /* Extension ... variable parameters. */
+      struct arg_list *next;
+    } arg_list;
+
+/* Each function has its own code segments and labels.  There can be
+   no jumps between functions so labels are unique to a function. */
+
+typedef struct 
+    {
+      char f_defined;   /* Is this function defined yet. */
+      char *f_body;
+      int  f_body_size;  /* Size of body.  Power of 2. */
+      int  f_code_size;
+      bc_label_group *f_label;
+      arg_list *f_params;
+      arg_list *f_autos;
+    } bc_function;
+
+/* Code addresses. */
+typedef struct {
+      int pc_func;
+      int pc_addr;
+    } program_counter;
+
+
+/* Variables are "pushable" (auto) and thus we need a stack mechanism.
+   This is built into the variable record. */
+
+typedef struct bc_var
+    {
+      bc_num v_value;
+      struct bc_var *v_next;
+    }  bc_var;
+
+
+/* bc arrays can also be "auto" variables and thus need the same
+   kind of stacking mechanisms. */
+
+typedef struct bc_array_node
+    {
+      union
+       {
+         bc_num n_num [NODE_SIZE];
+         struct bc_array_node *n_down [NODE_SIZE];
+       } n_items;
+    } bc_array_node;
+
+typedef struct bc_array
+    {
+      bc_array_node *a_tree;
+      short a_depth;
+    } bc_array;
+
+typedef struct bc_var_array
+    {
+      bc_array *a_value;
+      char      a_param;
+      struct bc_var_array *a_next;
+    } bc_var_array;
+
+
+/* For the stacks, execution and function, we need records to allow
+   for arbitrary size. */
+
+typedef struct estack_rec {
+       bc_num s_num;
+       struct estack_rec *s_next;
+} estack_rec;
+
+typedef struct fstack_rec {
+       int  s_val;
+       struct fstack_rec *s_next;
+} fstack_rec;
+
+
+/* The following are for the name tree. */
+
+typedef struct id_rec {
+       char  *id;      /* The program name. */
+                       /* A name == 0 => nothing assigned yet. */
+       int   a_name;   /* The array variable name (number). */
+       int   f_name;   /* The function name (number).  */
+       int   v_name;   /* The variable name (number).  */
+        short balance;  /* For the balanced tree. */
+       struct id_rec *left, *right; /* Tree pointers. */
+} id_rec;
+
+
+/* A list of files to process. */
+
+typedef struct file_node {
+       char *name;
+       struct file_node *next;
+} file_node;
+
+/* Macro Definitions */
+
+#if defined(LIBEDIT)
+#define HISTORY_SIZE(n) history(hist, &histev, H_SETSIZE, n)
+#define UNLIMIT_HISTORY history(hist, &histev, H_SETSIZE, INT_MAX)
+#endif
+
+#if defined(READLINE)
+#define HISTORY_SIZE(n) stifle_history(n)
+#define UNLIMIT_HISTORY unstifle_history()
+#endif
diff --git a/bc/const.h b/bc/const.h
new file mode 100644 (file)
index 0000000..1a7c5b8
--- /dev/null
@@ -0,0 +1,98 @@
+/* const.h: Constants for bc. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+/* Define INT_MAX and LONG_MAX if not defined.  Assuming 32 bits... */
+
+#ifndef INT_MAX
+#define INT_MAX 0x7FFFFFFF
+#endif
+#ifndef LONG_MAX
+#define LONG_MAX 0x7FFFFFFF
+#endif
+
+
+/* Define constants in some reasonable size.  The next 4 constants are
+   POSIX constants. */
+
+#ifdef BC_BASE_MAX
+  /* <limits.h> on a POSIX.2 system may have defined these.  Override. */
+# undef BC_BASE_MAX
+# undef BC_SCALE_MAX
+# undef BC_STRING_MAX
+# undef BC_DIM_MAX
+#endif
+
+#define BC_BASE_MAX   INT_MAX
+#define BC_SCALE_MAX  INT_MAX
+#define BC_STRING_MAX INT_MAX
+
+
+/* Definitions for arrays. */
+
+#define BC_DIM_MAX    65535       /* this should be NODE_SIZE^NODE_DEPTH-1 */
+
+#define   NODE_SIZE        16     /* Must be a power of 2. */
+#define   NODE_MASK       0xf     /* Must be NODE_SIZE-1. */
+#define   NODE_SHIFT        4     /* Number of 1 bits in NODE_MASK. */
+#define   NODE_DEPTH        4
+
+
+/* Other BC limits defined but not part of POSIX. */
+
+#define BC_LABEL_GROUP 64
+#define BC_LABEL_LOG    6
+#define BC_START_SIZE  1024    /* Initial code body size. */
+
+/* Maximum number of variables, arrays and functions and the
+   allocation increment for the dynamic arrays. */
+
+#define MAX_STORE   32767
+#define STORE_INCR     32
+
+/* Other interesting constants. */
+
+#define FALSE 0
+#define TRUE  1
+
+/* for use with lookup (). */
+#define SIMPLE   0
+#define ARRAY    1
+#define FUNCT    2
+#define FUNCTDEF 3
+
+#define EXTERN extern
+#ifdef __STDC__
+#define CONST const
+#define VOID  void
+#else
+#define CONST
+#define VOID
+#endif
diff --git a/bc/execute.c b/bc/execute.c
new file mode 100644 (file)
index 0000000..d2864d1
--- /dev/null
@@ -0,0 +1,788 @@
+/* execute.c - run a bc program. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include <signal.h>
+#include "global.h"
+#include "proto.h"
+
+
+/* The SIGINT interrupt handling routine. */
+
+int had_sigint;
+
+void
+stop_execution (sig)
+     int sig;
+{
+  had_sigint = TRUE;
+  printf ("\n");
+  rt_error ("interrupted execution");
+}
+
+
+/* Get the current byte and advance the PC counter. */
+
+unsigned char
+byte (pc)
+     program_counter *pc;
+{
+  return (functions[pc->pc_func].f_body[pc->pc_addr++]);
+}
+
+
+/* The routine that actually runs the machine. */
+
+void
+execute ()
+{
+  int label_num, l_gp, l_off;
+  bc_label_group *gp;
+  
+  char inst, ch;
+  int  new_func;
+  int  var_name;
+
+  int const_base;
+
+  bc_num temp_num;
+  arg_list *auto_list;
+
+  /* Initialize this run... */
+  pc.pc_func = 0;
+  pc.pc_addr = 0;
+  runtime_error = FALSE;
+  bc_init_num (&temp_num);
+
+  /* Set up the interrupt mechanism for an interactive session. */
+  if (interactive)
+    {
+      signal (SIGINT, stop_execution);
+      had_sigint = FALSE;
+    }
+   
+  while (pc.pc_addr < functions[pc.pc_func].f_code_size && !runtime_error)
+    {
+      inst = byte(&pc);
+
+#if DEBUG > 3
+      { /* Print out address and the stack before each instruction.*/
+       int depth; estack_rec *temp = ex_stack;
+       
+       printf ("func=%d addr=%d inst=%c\n",pc.pc_func, pc.pc_addr, inst);
+       if (temp == NULL) printf ("empty stack.\n", inst);
+       else
+         {
+           depth = 1;
+           while (temp != NULL)
+             {
+               printf ("  %d = ", depth);
+               bc_out_num (temp->s_num, 10, out_char, std_only);
+               depth++;
+               temp = temp->s_next;
+             }
+           out_char ('\n');
+         }
+      }
+#endif
+
+    switch ( inst )
+      {
+
+      case 'A' : /* increment array variable (Add one). */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       incr_array (var_name);
+       break;
+
+      case 'B' : /* Branch to a label if TOS != 0. Remove value on TOS. */
+      case 'Z' : /* Branch to a label if TOS == 0. Remove value on TOS. */
+       c_code = !bc_is_zero (ex_stack->s_num);
+       pop ();
+      case 'J' : /* Jump to a label. */
+       label_num = byte(&pc);  /* Low order bits first. */
+       label_num += byte(&pc) << 8;
+       if (inst == 'J' || (inst == 'B' && c_code)
+           || (inst == 'Z' && !c_code)) {
+         gp = functions[pc.pc_func].f_label;
+         l_gp  = label_num >> BC_LABEL_LOG;
+         l_off = label_num % BC_LABEL_GROUP;
+         while (l_gp-- > 0) gp = gp->l_next;
+         pc.pc_addr = gp->l_adrs[l_off];
+       }
+       break;
+
+      case 'C' : /* Call a function. */
+       /* Get the function number. */
+       new_func = byte(&pc);
+       if ((new_func & 0x80) != 0) 
+         new_func = ((new_func & 0x7f) << 8) + byte(&pc);
+
+       /* Check to make sure it is defined. */
+       if (!functions[new_func].f_defined)
+         {
+           rt_error ("Function %s not defined.", f_names[new_func]);
+           break;
+         }
+
+       /* Check and push parameters. */
+       process_params (&pc, new_func);
+
+       /* Push auto variables. */
+       for (auto_list = functions[new_func].f_autos;
+            auto_list != NULL;
+            auto_list = auto_list->next)
+         auto_var (auto_list->av_name);
+
+       /* Push pc and ibase. */
+       fpush (pc.pc_func);
+       fpush (pc.pc_addr);
+       fpush (i_base);
+
+       /* Reset pc to start of function. */
+       pc.pc_func = new_func;
+       pc.pc_addr = 0;
+       break;
+
+      case 'D' : /* Duplicate top of stack */
+       push_copy (ex_stack->s_num);
+       break;
+
+      case 'K' : /* Push a constant */
+       /* Get the input base and convert it to a bc number. */
+       if (pc.pc_func == 0) 
+         const_base = i_base;
+       else
+         const_base = fn_stack->s_val;
+       if (const_base == 10)
+         push_b10_const (&pc);
+       else
+         push_constant (prog_char, const_base);
+       break;
+
+      case 'L' : /* load array variable */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       load_array (var_name);
+       break;
+
+      case 'M' : /* decrement array variable (Minus!) */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       decr_array (var_name);
+       break;
+
+      case 'O' : /* Write a string to the output with processing. */
+       while ((ch = byte(&pc)) != '"')
+         if (ch != '\\')
+           out_schar (ch);
+         else
+           {
+             ch = byte(&pc);
+             if (ch == '"') break;
+             switch (ch)
+               {
+               case 'a':  out_schar (007); break;
+               case 'b':  out_schar ('\b'); break;
+               case 'f':  out_schar ('\f'); break;
+               case 'n':  out_schar ('\n'); break;
+               case 'q':  out_schar ('"'); break;
+               case 'r':  out_schar ('\r'); break;
+               case 't':  out_schar ('\t'); break;
+               case '\\': out_schar ('\\'); break;
+               default:  break;
+               }
+           }
+       fflush (stdout);
+       break;
+
+      case 'R' : /* Return from function */
+       if (pc.pc_func != 0)
+         {
+           /* "Pop" autos and parameters. */
+           pop_vars(functions[pc.pc_func].f_autos);
+           pop_vars(functions[pc.pc_func].f_params);
+           /* reset the pc. */
+           fpop ();
+           pc.pc_addr = fpop ();
+           pc.pc_func = fpop ();
+         }
+       else
+         rt_error ("Return from main program.");
+       break;
+
+      case 'S' : /* store array variable */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f ) << 8) + byte(&pc);
+       store_array (var_name);
+       break;
+
+      case 'T' : /* Test tos for zero */
+       c_code = bc_is_zero (ex_stack->s_num);
+       assign (c_code);
+       break;
+
+      case 'W' : /* Write the value on the top of the stack. */
+      case 'P' : /* Write the value on the top of the stack.  No newline. */
+       bc_out_num (ex_stack->s_num, o_base, out_char, std_only);
+       if (inst == 'W') out_char ('\n');
+       store_var (4);  /* Special variable "last". */
+       fflush (stdout);
+       pop ();
+       break;
+
+      case 'c' : /* Call special function. */
+       new_func = byte(&pc);
+
+      switch (new_func)
+       {
+       case 'L':  /* Length function. */
+         /* For the number 0.xxxx,  0 is not significant. */
+         if (ex_stack->s_num->n_len == 1 &&
+             ex_stack->s_num->n_scale != 0 &&
+             ex_stack->s_num->n_value[0] == 0 )
+           bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
+         else
+           bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_len
+                    + ex_stack->s_num->n_scale);
+         break;
+               
+       case 'S':  /* Scale function. */ 
+         bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
+         break;
+
+       case 'R':  /* Square Root function. */
+         if (!bc_sqrt (&ex_stack->s_num, scale))
+           rt_error ("Square root of a negative number");
+         break;
+
+       case 'I': /* Read function. */
+         push_constant (input_char, i_base);
+         break;
+       }
+       break;
+
+      case 'd' : /* Decrement number */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       decr_var (var_name);
+       break;
+      
+      case 'h' : /* Halt the machine. */
+       exit (0);
+
+      case 'i' : /* increment number */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       incr_var (var_name);
+       break;
+
+      case 'l' : /* load variable */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       load_var (var_name);
+       break;
+
+      case 'n' : /* Negate top of stack. */
+       bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num, 0);
+       break;
+
+      case 'p' : /* Pop the execution stack. */
+       pop ();
+       break;
+
+      case 's' : /* store variable */
+       var_name = byte(&pc);
+       if ((var_name & 0x80) != 0)
+         var_name = ((var_name & 0x7f) << 8) + byte(&pc);
+       store_var (var_name);
+       break;
+
+      case 'w' : /* Write a string to the output. */
+       while ((ch = byte(&pc)) != '"') out_schar (ch);
+       fflush (stdout);
+       break;
+                  
+      case 'x' : /* Exchange Top of Stack with the one under the tos. */
+       if (check_stack(2)) {
+         bc_num temp = ex_stack->s_num;
+         ex_stack->s_num = ex_stack->s_next->s_num;
+         ex_stack->s_next->s_num = temp;
+       }
+       break;
+
+      case '0' : /* Load Constant 0. */
+       push_copy (_zero_);
+       break;
+
+      case '1' : /* Load Constant 0. */
+       push_copy (_one_);
+       break;
+
+      case '!' : /* Negate the boolean value on top of the stack. */
+       c_code = bc_is_zero (ex_stack->s_num);
+       assign (c_code);
+       break;
+
+      case '&' : /* compare greater than */
+       if (check_stack(2))
+         {
+           c_code = !bc_is_zero (ex_stack->s_next->s_num)
+             && !bc_is_zero (ex_stack->s_num);
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '|' : /* compare greater than */
+       if (check_stack(2))
+         {
+           c_code = !bc_is_zero (ex_stack->s_next->s_num)
+             || !bc_is_zero (ex_stack->s_num);
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '+' : /* add */
+       if (check_stack(2))
+         {
+           bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
+           pop();
+           pop();
+           push_num (temp_num);
+           bc_init_num (&temp_num);
+         }
+       break;
+
+      case '-' : /* subtract */
+       if (check_stack(2))
+         {
+           bc_sub (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
+           pop();
+           pop();
+           push_num (temp_num);
+           bc_init_num (&temp_num);
+         }
+       break;
+
+      case '*' : /* multiply */
+       if (check_stack(2))
+         {
+           bc_multiply (ex_stack->s_next->s_num, ex_stack->s_num,
+                        &temp_num, scale);
+           pop();
+           pop();
+           push_num (temp_num);
+           bc_init_num (&temp_num);
+         }
+       break;
+
+      case '/' : /* divide */
+       if (check_stack(2))
+         {
+           if (bc_divide (ex_stack->s_next->s_num,
+                          ex_stack->s_num, &temp_num, scale) == 0)
+             {
+               pop();
+               pop();
+               push_num (temp_num);
+               bc_init_num (&temp_num);
+             }
+           else
+             rt_error ("Divide by zero");
+         }
+       break;
+
+      case '%' : /* remainder */
+       if (check_stack(2))
+         {
+           if (bc_is_zero (ex_stack->s_num))
+             rt_error ("Modulo by zero");
+           else
+             {
+               bc_modulo (ex_stack->s_next->s_num,
+                          ex_stack->s_num, &temp_num, scale);
+               pop();
+               pop();
+               push_num (temp_num);
+               bc_init_num (&temp_num);
+             }
+         }
+       break;
+
+      case '^' : /* raise */
+       if (check_stack(2))
+         {
+           bc_raise (ex_stack->s_next->s_num,
+                     ex_stack->s_num, &temp_num, scale);
+           if (bc_is_zero (ex_stack->s_next->s_num) && bc_is_neg (ex_stack->s_num))
+             rt_error ("divide by zero");
+           pop();
+           pop();
+           push_num (temp_num);
+           bc_init_num (&temp_num);
+         }
+       break;
+
+      case '=' : /* compare equal */
+       if (check_stack(2))
+         {
+           c_code = bc_compare (ex_stack->s_next->s_num,
+                                ex_stack->s_num) == 0;
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '#' : /* compare not equal */
+       if (check_stack(2))
+         {
+           c_code = bc_compare (ex_stack->s_next->s_num,
+                                ex_stack->s_num) != 0;
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '<' : /* compare less than */
+       if (check_stack(2))
+         {
+           c_code = bc_compare (ex_stack->s_next->s_num,
+                                ex_stack->s_num) == -1;
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '{' : /* compare less than or equal */
+       if (check_stack(2))
+         {
+           c_code = bc_compare (ex_stack->s_next->s_num,
+                                ex_stack->s_num) <= 0;
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '>' : /* compare greater than */
+       if (check_stack(2))
+         {
+           c_code = bc_compare (ex_stack->s_next->s_num,
+                                ex_stack->s_num) == 1;
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+      case '}' : /* compare greater than or equal */
+       if (check_stack(2))
+         {
+           c_code = bc_compare (ex_stack->s_next->s_num,
+                                ex_stack->s_num) >= 0;
+           pop ();
+           assign (c_code);
+         }
+       break;
+
+       default  : /* error! */
+         rt_error ("bad instruction: inst=%c", inst);
+      }
+    }
+
+  /* Clean up the function stack and pop all autos/parameters. */
+  while (pc.pc_func != 0)
+    {
+      pop_vars(functions[pc.pc_func].f_autos);
+      pop_vars(functions[pc.pc_func].f_params);
+      fpop ();
+      pc.pc_addr = fpop ();
+      pc.pc_func = fpop ();
+    }
+
+  /* Clean up the execution stack. */ 
+  while (ex_stack != NULL) pop();
+
+  /* Clean up the interrupt stuff. */
+  if (interactive)
+    {
+      signal (SIGINT, use_quit);
+      if (had_sigint)
+       printf ("Interruption completed.\n");
+    }
+}
+
+
+/* Prog_char gets another byte from the program.  It is used for
+   conversion of text constants in the code to numbers. */
+
+char
+prog_char ()
+{
+  return byte(&pc);
+}
+
+
+/* Read a character from the standard input.  This function is used
+   by the "read" function. */
+
+char
+input_char ()
+{
+  char in_ch;
+  
+  /* Get a character from the standard input for the read function. */
+  in_ch = getchar();
+
+  /* Check for a \ quoted newline. */
+  if (in_ch == '\\')
+    {
+      in_ch = getchar();
+      if (in_ch == '\n')
+       in_ch = getchar();
+    }
+
+  /* Classify and preprocess the input character. */
+  if (isdigit((int)in_ch))
+    return (in_ch - '0');
+  if (in_ch >= 'A' && in_ch <= 'F')
+    return (in_ch + 10 - 'A');
+  if (in_ch >= 'a' && in_ch <= 'f')
+    return (in_ch + 10 - 'a');
+  if (in_ch == '.' || in_ch == '+' || in_ch == '-')
+    return (in_ch);
+  if (in_ch <= ' ')
+    return (' ');
+  
+  return (':');
+}
+
+
+/* Push_constant converts a sequence of input characters as returned
+   by IN_CHAR into a number.  The number is pushed onto the execution
+   stack.  The number is converted as a number in base CONV_BASE. */
+
+void
+push_constant (in_char, conv_base)
+   char (*in_char)(VOID);
+   int conv_base;
+{
+  int digits;
+  bc_num build, temp, result, mult, divisor;
+  char  in_ch, first_ch;
+  char  negative;
+
+  /* Initialize all bc numbers */
+  bc_init_num (&temp);
+  bc_init_num (&result);
+  bc_init_num (&mult);
+  build = bc_copy_num (_zero_);
+  negative = FALSE;
+
+  /* The conversion base. */
+  bc_int2num (&mult, conv_base);
+  
+  /* Get things ready. */
+  in_ch = in_char();
+  while (in_ch == ' ')
+    in_ch = in_char();
+
+  if (in_ch == '+')
+    in_ch = in_char();
+  else
+    if (in_ch == '-')
+      {
+       negative = TRUE;
+       in_ch = in_char();
+      }
+
+  /* Check for the special case of a single digit. */
+  if (in_ch < 16)
+    {
+      first_ch = in_ch;
+      in_ch = in_char();
+      if (in_ch < 16 && first_ch >= conv_base)
+       first_ch = conv_base - 1;
+      bc_int2num (&build, (int) first_ch);
+    }
+
+  /* Convert the integer part. */
+  while (in_ch < 16)
+    {
+      if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
+      bc_multiply (build, mult, &result, 0);
+      bc_int2num (&temp, (int) in_ch);
+      bc_add (result, temp, &build, 0);
+      in_ch = in_char();
+    }
+  if (in_ch == '.')
+    {
+      in_ch = in_char();
+      if (in_ch >= conv_base) in_ch = conv_base-1;
+      bc_free_num (&result);
+      bc_free_num (&temp);
+      divisor = bc_copy_num (_one_);
+      result = bc_copy_num (_zero_);
+      digits = 0;
+      while (in_ch < 16)
+       {
+         bc_multiply (result, mult, &result, 0);
+         bc_int2num (&temp, (int) in_ch);
+         bc_add (result, temp, &result, 0);
+         bc_multiply (divisor, mult, &divisor, 0);
+         digits++;
+         in_ch = in_char();
+         if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
+       }
+      bc_divide (result, divisor, &result, digits);
+      bc_add (build, result, &build, 0);
+    }
+  
+  /* Final work.  */
+  if (negative)
+    bc_sub (_zero_, build, &build, 0);
+
+  push_num (build);
+  bc_free_num (&temp);
+  bc_free_num (&result);
+  bc_free_num (&mult);
+}
+
+
+/* When converting base 10 constants from the program, we use this
+   more efficient way to convert them to numbers.  PC tells where
+   the constant starts and is expected to be advanced to after
+   the constant. */
+
+void
+push_b10_const (pc)
+     program_counter *pc;
+{
+  bc_num build;
+  program_counter look_pc;
+  int kdigits, kscale;
+  char inchar;
+  char *ptr;
+  
+  /* Count the digits and get things ready. */
+  look_pc = *pc;
+  kdigits = 0;
+  kscale  = 0;
+  inchar = byte (&look_pc);
+  while (inchar != '.' && inchar != ':')
+    {
+      kdigits++;
+      inchar = byte(&look_pc);
+    }
+  if (inchar == '.' )
+    {
+      inchar = byte(&look_pc);
+      while (inchar != ':')
+       {
+         kscale++;
+         inchar = byte(&look_pc);
+       }
+    }
+
+  /* Get the first character again and move the pc. */
+  inchar = byte(pc);
+  
+  /* Secial cases of 0, 1, and A-F single inputs. */
+  if (kdigits == 1 && kscale == 0)
+    {
+      if (inchar == 0)
+       {
+         push_copy (_zero_);
+         inchar = byte(pc);
+         return;
+       }
+      if (inchar == 1) {
+      push_copy (_one_);
+      inchar = byte(pc);
+      return;
+    }
+    if (inchar > 9)
+      {
+       bc_init_num (&build);
+       bc_int2num (&build, inchar);
+       push_num (build);
+       inchar = byte(pc);
+       return;
+      }
+    }
+
+  /* Build the new number. */
+  if (kdigits == 0)
+    {
+      build = bc_new_num (1,kscale);
+      ptr = build->n_value;
+      *ptr++ = 0;
+    }
+  else
+    {
+      build = bc_new_num (kdigits,kscale);
+      ptr = build->n_value;
+    }
+
+  while (inchar != ':')
+    {
+      if (inchar != '.')
+       {
+         if (inchar > 9)
+           *ptr++ = 9;
+         else
+           *ptr++ = inchar;
+       }
+      inchar = byte(pc);
+    }
+  push_num (build);
+}
+
+
+/* Put the correct value on the stack for C_CODE.  Frees TOS num. */
+
+void
+assign (c_code)
+     char c_code;
+{
+  bc_free_num (&ex_stack->s_num);
+  if (c_code)
+    ex_stack->s_num = bc_copy_num (_one_);
+  else
+    ex_stack->s_num = bc_copy_num (_zero_);
+}
+
diff --git a/bc/fix-libmath_h b/bc/fix-libmath_h
new file mode 100755 (executable)
index 0000000..f973a8c
--- /dev/null
@@ -0,0 +1,9 @@
+ed libmath.h <<EOS-EOS
+1,1s/^/{"/
+1,\$s/\$/",/
+2,\$s/^/"/
+\$,\$d
+\$,\$s/,\$/,0}/
+w
+q
+EOS-EOS
diff --git a/bc/global.c b/bc/global.c
new file mode 100644 (file)
index 0000000..5d1205c
--- /dev/null
@@ -0,0 +1,42 @@
+/* global.c:  This defines the global variables. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+
+/* Since we want to define them here, we use the following define. */
+#undef EXTERN
+#define EXTERN
+
+/* Define all the global variables for bc. */
+#include "global.h"
+
+CONST char *libmath[] = 
+#include "libmath.h"
+;
diff --git a/bc/global.h b/bc/global.h
new file mode 100644 (file)
index 0000000..cf6945c
--- /dev/null
@@ -0,0 +1,154 @@
+/* global.h:  The global variables for bc.  */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+/* The current break level's lable. */
+EXTERN int break_label;
+
+/* The current if statement's else label or label after else. */
+EXTERN int if_label;
+
+/* The current for statement label for continuing the loop. */
+EXTERN int continue_label;
+
+/* Next available label number. */
+EXTERN int next_label;
+
+/* Byte code character storage.  Used in many places for generation of code. */
+EXTERN char genstr[80];
+
+/* Count of characters printed to the output in compile_only mode. */
+EXTERN int out_count;
+
+/* Have we generated any code since the last initialization of the code
+   generator.  */
+EXTERN char did_gen;
+
+/* Is this run an interactive execution.  (Is stdin a terminal?) */
+EXTERN char interactive;
+
+/* Just generate the byte code.  -c flag. */
+EXTERN int compile_only;
+
+/* Load the standard math functions.  -l flag. */
+EXTERN int use_math;
+
+/* Give a warning on use of any non-standard feature (non-POSIX).  -w flag. */
+EXTERN int warn_not_std;
+
+/* Accept POSIX bc only!  -s flag. */
+EXTERN int std_only;
+
+/* Don't print the banner at start up.  -q flag. */
+EXTERN int quiet;
+
+/* The list of file names to process. */
+EXTERN file_node *file_names;
+
+/* The name of the current file being processed. */
+EXTERN char *file_name;
+
+/* Is the current file a named file or standard input? */
+EXTERN char   is_std_in;
+
+/* global variables for the bc machine. All will be dynamic in size.*/
+/* Function storage. main is (0) and functions (1-f_count) */
+
+EXTERN bc_function *functions;
+EXTERN char **f_names;
+EXTERN int  f_count;
+
+/* Variable stoarge and reverse names. */
+
+EXTERN bc_var **variables;
+EXTERN char **v_names;
+EXTERN int  v_count;
+
+/* Array Variable storage and reverse names. */
+
+EXTERN bc_var_array **arrays;
+EXTERN char **a_names;
+EXTERN int  a_count;
+
+/* Execution stack. */
+EXTERN estack_rec *ex_stack;
+
+/* Function return stack. */
+EXTERN fstack_rec *fn_stack;
+
+/* Current ibase, obase, scale, and n_history (if needed). */
+EXTERN int i_base;
+EXTERN int o_base;
+EXTERN int scale;
+#if defined(READLINE) || defined(LIBEDIT)
+EXTERN int n_history;
+#endif
+
+#if defined(LIBEDIT)
+/* LIBEDIT data */
+EditLine *edit;
+History  *hist;
+HistEvent histev;
+#endif
+
+/* "Condition code" -- false (0) or true (1) */
+EXTERN char c_code;
+
+/* Records the number of the runtime error. */
+EXTERN char runtime_error;
+
+/* Holds the current location of execution. */
+EXTERN program_counter pc;
+
+/* For POSIX bc, this is just for number output, not strings. */
+EXTERN int out_col;
+
+/* Keeps track of the current number of characters per output line.
+   This includes the \n at the end of the line. */
+EXTERN int line_size;
+
+/* Input Line numbers and other error information. */
+EXTERN int line_no;
+EXTERN int had_error;
+
+/* For larger identifiers, a tree, and how many "storage" locations
+   have been allocated. */
+
+EXTERN int next_array;
+EXTERN int next_func;
+EXTERN int next_var;
+
+EXTERN id_rec *name_tree;
+
+/* For use with getopt.  Do not declare them here.*/
+extern int optind;
+
+/* Access to the yy input file.  Defined in scan.c. */
+extern FILE *yyin;
diff --git a/bc/libmath.b b/bc/libmath.b
new file mode 100644 (file)
index 0000000..7bb6405
--- /dev/null
@@ -0,0 +1,287 @@
+/* libmath.b for GNU bc.  */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+scale = 20
+
+/* Uses the fact that e^x = (e^(x/2))^2
+   When x is small enough, we use the series:
+     e^x = 1 + x + x^2/2! + x^3/3! + ...
+*/
+
+define e(x) {
+  auto  a, d, e, f, i, m, n, v, z
+
+  /* a - holds x^y of x^y/y! */
+  /* d - holds y! */
+  /* e - is the value x^y/y! */
+  /* v - is the sum of the e's */
+  /* f - number of times x was divided by 2. */
+  /* m - is 1 if x was minus. */
+  /* i - iteration count. */
+  /* n - the scale to compute the sum. */
+  /* z - orignal scale. */
+
+  /* Check the sign of x. */
+  if (x<0) {
+    m = 1
+    x = -x
+  } 
+
+  /* Precondition x. */
+  z = scale;
+  n = 6 + z + .44*x;
+  scale = scale(x)+1;
+  while (x > 1) {
+    f += 1;
+    x /= 2;
+    scale += 1;
+  }
+
+  /* Initialize the variables. */
+  scale = n;
+  v = 1+x
+  a = x
+  d = 1
+
+  for (i=2; 1; i++) {
+    e = (a *= x) / (d *= i)
+    if (e == 0) {
+      if (f>0) while (f--)  v = v*v;
+      scale = z
+      if (m) return (1/v);
+      return (v/1);
+    }
+    v += e
+  }
+}
+
+/* Natural log. Uses the fact that ln(x^2) = 2*ln(x)
+    The series used is:
+       ln(x) = 2(a+a^3/3+a^5/5+...) where a=(x-1)/(x+1)
+*/
+
+define l(x) {
+  auto e, f, i, m, n, v, z
+
+  /* return something for the special case. */
+  if (x <= 0) return ((1 - 10^scale)/1)
+
+  /* Precondition x to make .5 < x < 2.0. */
+  z = scale;
+  scale = 6 + scale;
+  f = 2;
+  i=0
+  while (x >= 2) {  /* for large numbers */
+    f *= 2;
+    x = sqrt(x);
+  }
+  while (x <= .5) {  /* for small numbers */
+    f *= 2;
+    x = sqrt(x);
+  }
+
+  /* Set up the loop. */
+  v = n = (x-1)/(x+1)
+  m = n*n
+
+  /* Sum the series. */
+  for (i=3; 1; i+=2) {
+    e = (n *= m) / i
+    if (e == 0) {
+      v = f*v
+      scale = z
+      return (v/1)
+    }
+    v += e
+  }
+}
+
+/* Sin(x)  uses the standard series:
+   sin(x) = x - x^3/3! + x^5/5! - x^7/7! ... */
+
+define s(x) {
+  auto  e, i, m, n, s, v, z
+
+  /* precondition x. */
+  z = scale 
+  scale = 1.1*z + 2;
+  v = a(1)
+  if (x < 0) {
+    m = 1;
+    x = -x;
+  }
+  scale = 0
+  n = (x / v + 2 )/4
+  x = x - 4*n*v
+  if (n%2) x = -x
+
+  /* Do the loop. */
+  scale = z + 2;
+  v = e = x
+  s = -x*x
+  for (i=3; 1; i+=2) {
+    e *= s/(i*(i-1))
+    if (e == 0) {
+      scale = z
+      if (m) return (-v/1);
+      return (v/1);
+    }
+    v += e
+  }
+}
+
+/* Cosine : cos(x) = sin(x+pi/2) */
+define c(x) {
+  auto v, z;
+  z = scale;
+  scale = scale*1.2;
+  v = s(x+a(1)*2);
+  scale = z;
+  return (v/1);
+}
+
+/* Arctan: Using the formula:
+     atan(x) = atan(c) + atan((x-c)/(1+xc)) for a small c (.2 here)
+   For under .2, use the series:
+     atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...   */
+
+define a(x) {
+  auto a, e, f, i, m, n, s, v, z
+
+  /* a is the value of a(.2) if it is needed. */
+  /* f is the value to multiply by a in the return. */
+  /* e is the value of the current term in the series. */
+  /* v is the accumulated value of the series. */
+  /* m is 1 or -1 depending on x (-x -> -1).  results are divided by m. */
+  /* i is the denominator value for series element. */
+  /* n is the numerator value for the series element. */
+  /* s is -x*x. */
+  /* z is the saved user's scale. */
+
+  /* Negative x? */
+  m = 1;
+  if (x<0) {
+    m = -1;
+    x = -x;
+  }
+
+  /* Special case and for fast answers */
+  if (x==1) {
+    if (scale <= 25) return (.7853981633974483096156608/m)
+    if (scale <= 40) return (.7853981633974483096156608458198757210492/m)
+    if (scale <= 60) \
+      return (.785398163397448309615660845819875721049292349843776455243736/m)
+  }
+  if (x==.2) {
+    if (scale <= 25) return (.1973955598498807583700497/m)
+    if (scale <= 40) return (.1973955598498807583700497651947902934475/m)
+    if (scale <= 60) \
+      return (.197395559849880758370049765194790293447585103787852101517688/m)
+  }
+
+
+  /* Save the scale. */
+  z = scale;
+
+  /* Note: a and f are known to be zero due to being auto vars. */
+  /* Calculate atan of a known number. */ 
+  if (x > .2)  {
+    scale = z+5;
+    a = a(.2);
+  }
+   
+  /* Precondition x. */
+  scale = z+3;
+  while (x > .2) {
+    f += 1;
+    x = (x-.2) / (1+x*.2);
+  }
+
+  /* Initialize the series. */
+  v = n = x;
+  s = -x*x;
+
+  /* Calculate the series. */
+  for (i=3; 1; i+=2) {
+    e = (n *= s) / i;
+    if (e == 0) {
+      scale = z;
+      return ((f*a+v)/m);
+    }
+    v += e
+  }
+}
+
+
+/* Bessel function of integer order.  Uses the following:
+   j(-n,x) = (-1)^n*j(n,x) 
+   j(n,x) = x^n/(2^n*n!) * (1 - x^2/(2^2*1!*(n+1)) + x^4/(2^4*2!*(n+1)*(n+2))
+            - x^6/(2^6*3!*(n+1)*(n+2)*(n+3)) .... )
+*/
+define j(n,x) {
+  auto a, b, d, e, f, i, m, s, v, z
+
+  /* Make n an integer and check for negative n. */
+  z = scale;
+  scale = 0;
+  n = n/1;
+  if (n<0) {
+    n = -n;
+    if (n%2 == 1) m = 1;
+  }
+
+  /* save ibase */
+  b = ibase;
+  ibase = A;
+
+  /* Compute the factor of x^n/(2^n*n!) */
+  f = 1;
+  for (i=2; i<=n; i++) f = f*i;
+  scale = 1.5*z;
+  f = x^n / 2^n / f;
+
+  /* Initialize the loop .*/
+  v = e = 1;
+  s = -x*x/4
+  scale = 1.5*z + length(f) - scale(f);
+
+  /* The Loop.... */
+  for (i=1; 1; i++) {
+    e =  e * s / i / (n+i);
+    if (e == 0) {
+       ibase = b;
+       scale = z
+       if (m) return (-f*v/1);
+       return (f*v/1);
+    }
+    v += e;
+  }
+}
diff --git a/bc/libmath.h b/bc/libmath.h
new file mode 100644 (file)
index 0000000..7611e11
--- /dev/null
@@ -0,0 +1 @@
+{0}
diff --git a/bc/load.c b/bc/load.c
new file mode 100644 (file)
index 0000000..7465481
--- /dev/null
+++ b/bc/load.c
@@ -0,0 +1,351 @@
+/* load.c:  This code "loads" code into the code segments. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+
+/* Load variables. */
+
+program_counter load_adr;
+char load_str;
+char load_const;
+
+/* Initialize the load sequence. */
+void
+init_load ()
+{
+  clear_func(0);
+  load_adr.pc_func = 0;
+  load_adr.pc_addr = 0;
+  load_str = FALSE;
+  load_const = FALSE;
+}
+
+/* addbyte adds one BYTE to the current code segment. */
+void
+addbyte (byte)
+     char byte;
+{
+  int pc;
+  bc_function *f;
+  char *new_body;
+
+  /* If there was an error, don't continue. */
+  if (had_error) return;
+
+  /* Calculate the segment and offset. */
+  pc = load_adr.pc_addr++;
+  f = &functions[load_adr.pc_func];
+
+  if (pc >= f->f_body_size)
+    {
+      f->f_body_size *= 2;
+      new_body = (char *) bc_malloc (f->f_body_size);
+      memcpy(new_body, f->f_body, f->f_body_size/2);
+      free (f->f_body);
+      f->f_body = new_body;
+    }
+
+  /* Store the byte. */
+  f->f_body[pc] = byte;
+  f->f_code_size++;
+}
+
+
+/* Define a label LAB to be the current program counter. */
+
+void
+def_label (lab)
+     long lab;
+{
+  bc_label_group *temp;
+  int group, offset, func;
+    
+  /* Get things ready. */
+  group = lab >> BC_LABEL_LOG;
+  offset = lab % BC_LABEL_GROUP;
+  func = load_adr.pc_func;
+  
+  /* Make sure there is at least one label group. */
+  if (functions[func].f_label == NULL)
+    {
+      functions[func].f_label = 
+       (bc_label_group *) bc_malloc (sizeof(bc_label_group));
+      functions[func].f_label->l_next = NULL;
+    }
+
+  /* Add the label group. */
+  temp = functions[func].f_label;
+  while (group > 0)
+    {
+      if (temp->l_next == NULL)
+       {
+         temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
+         temp->l_next->l_next = NULL;
+       }
+      temp = temp->l_next;
+      group --;
+    }
+
+  /* Define it! */
+  temp->l_adrs [offset] = load_adr.pc_addr;
+}
+
+/* Several instructions have integers in the code.  They
+   are all known to be legal longs.  So, no error code
+   is added.  STR is the pointer to the load string and
+   must be moved to the last non-digit character. */
+
+long
+long_val (str)
+     char **str;
+{ int  val = 0;
+  char neg = FALSE;
+
+  if (**str == '-')
+    {
+      neg = TRUE;
+      (*str)++;
+    }
+  while (isdigit((int)(**str))) 
+    val = val*10 + *(*str)++ - '0';
+
+  if (neg)
+    return -val;
+  else
+    return val;
+}
+
+
+/* load_code loads the CODE into the machine. */
+
+void
+load_code (code)
+     char *code;
+{
+  char *str;
+  long  ap_name;       /* auto or parameter name. */
+  long  label_no;
+  long  vaf_name;      /* variable, array or function number. */
+  long  func;
+  program_counter save_adr = { 0, 0 };;
+
+  /* Initialize. */
+  str = code;
+   
+  /* Scan the code. */
+  while (*str != 0)
+    {
+      /* If there was an error, don't continue. */
+      if (had_error) return;
+
+      if (load_str)
+       {
+         if (*str == '"') load_str = FALSE;
+         addbyte (*str++);
+       }
+      else
+       if (load_const)
+         {
+           if (*str == '\n') 
+             str++;
+           else
+             {
+               if (*str == ':')
+                 {
+                   load_const = FALSE;
+                   addbyte (*str++);
+                 }
+               else
+                 if (*str == '.')
+                   addbyte (*str++);
+                 else
+                   if (*str >= 'A')
+                     addbyte (*str++ + 10 - 'A');
+                   else
+                     addbyte (*str++ - '0');
+             }
+         }
+       else
+         {
+           switch (*str)
+             {
+
+             case '"': /* Starts a string. */
+               load_str = TRUE;
+               break;
+
+             case 'N': /* A label */
+               str++;
+               label_no = long_val (&str);
+               def_label (label_no);
+               break;
+
+             case 'B':  /* Branch to label. */
+             case 'J':  /* Jump to label. */
+             case 'Z':  /* Branch Zero to label. */
+               addbyte(*str++);
+               label_no = long_val (&str);
+               if (label_no > 65535L)
+                 {  /* Better message? */
+                   fprintf (stderr,"Program too big.\n");
+                   exit(1);
+                 }
+               addbyte ( (char) (label_no & 0xFF));
+               addbyte ( (char) (label_no >> 8));
+               break;
+
+             case 'F':  /* A function, get the name and initialize it. */
+               str++;
+               func = long_val (&str);
+               clear_func (func);
+#if DEBUG > 2
+               printf ("Loading function number %d\n", func);
+#endif
+               /* get the parameters */
+               while (*str++ != '.')
+                 {
+                   if (*str == '.')
+                     {
+                       str++;
+                       break;
+                     }
+                   if (*str == '*')
+                     {
+                       str++;
+                       ap_name = long_val (&str);
+#if DEBUG > 2
+                       printf ("var parameter number %d\n", ap_name);
+#endif
+                       functions[(int)func].f_params = 
+                         nextarg (functions[(int)func].f_params, ap_name,
+                                  TRUE);
+                     }
+                   else
+                     {
+                       ap_name = long_val (&str);
+#if DEBUG > 2
+                       printf ("parameter number %d\n", ap_name);
+#endif
+                       functions[(int)func].f_params = 
+                         nextarg (functions[(int)func].f_params, ap_name,
+                                  FALSE);
+                     }
+                 }
+
+               /* get the auto vars */
+               while (*str != '[')
+                 {
+                   if (*str == ',') str++;
+                   ap_name = long_val (&str);
+#if DEBUG > 2
+                   printf ("auto number %d\n", ap_name);
+#endif
+                   functions[(int)func].f_autos = 
+                     nextarg (functions[(int)func].f_autos, ap_name, FALSE);
+                 }
+               save_adr = load_adr;
+               load_adr.pc_func = func;
+               load_adr.pc_addr = 0;
+               break;
+               
+             case ']':  /* A function end */
+               functions[load_adr.pc_func].f_defined = TRUE;
+               load_adr = save_adr;
+               break;
+
+             case 'C':  /* Call a function. */
+               addbyte (*str++);
+               func = long_val (&str);
+               if (func < 128)
+                 addbyte ( (char) func);
+               else
+                 {
+                   addbyte (((func >> 8) & 0xff) | 0x80);
+                   addbyte (func & 0xff);
+                 }
+               if (*str == ',') str++;
+               while (*str != ':')
+                 addbyte (*str++);
+               addbyte (':');
+               break;
+               
+             case 'c':  /* Call a special function. */
+               addbyte (*str++);
+               addbyte (*str);
+               break;
+
+             case 'K':  /* A constant.... may have an "F" in it. */
+               addbyte (*str);
+               load_const = TRUE;
+               break;
+
+             case 'd':  /* Decrement. */
+             case 'i':  /* Increment. */
+             case 'l':  /* Load. */
+             case 's':  /* Store. */
+             case 'A':  /* Array Increment */
+             case 'M':  /* Array Decrement */
+             case 'L':  /* Array Load */
+             case 'S':  /* Array Store */
+               addbyte (*str++);
+               vaf_name = long_val (&str);
+               if (vaf_name < 128)
+                 addbyte (vaf_name);
+               else
+                 {
+                   addbyte (((vaf_name >> 8) & 0xff) | 0x80);
+                   addbyte (vaf_name & 0xff);
+                 }
+               break;
+
+             case '@':  /* A command! */
+               switch (*(++str))
+                 {
+                 case 'i':
+                   init_load ();
+                   break;
+                 case 'r':
+                   execute ();
+                   break;
+                 } 
+               break;
+
+             case '\n':  /* Ignore the newlines */
+               break;
+               
+             default:   /* Anything else */
+               addbyte (*str);    
+             }
+           str++;
+         }
+    }
+}
diff --git a/bc/main.c b/bc/main.c
new file mode 100644 (file)
index 0000000..b94525f
--- /dev/null
+++ b/bc/main.c
@@ -0,0 +1,355 @@
+/* main.c: The main program for bc.  */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 1998, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include <signal.h>
+#include "global.h"
+#include "proto.h"
+#include "getopt.h"
+
+
+/* Variables for processing multiple files. */
+static char first_file;
+
+/* Points to the last node in the file name list for easy adding. */
+static file_node *last = NULL;
+
+/* long option support */
+static struct option long_options[] =
+{
+  {"compile",  0, &compile_only, TRUE},
+  {"help",     0, 0,             'h'},
+  {"interactive", 0, 0,          'i'},
+  {"mathlib",  0, &use_math,     TRUE},
+  {"quiet",    0, &quiet,        TRUE},
+  {"standard", 0, &std_only,     TRUE},
+  {"version",  0, 0,             'v'},
+  {"warn",     0, &warn_not_std, TRUE},
+
+  {0, 0, 0, 0}
+};
+
+
+void
+usage (char *progname)
+{
+  printf ("usage: %s [options] [file ...]\n%s%s%s%s%s%s%s", progname,
+          "  -h  --help         print this usage and exit\n",
+         "  -i  --interactive  force interactive mode\n",
+         "  -l  --mathlib      use the predefine math routnes\n",
+         "  -q  --quiet        don't print initial banner\n",
+         "  -s  --standard     non-standard bc constructs are errors\n",
+         "  -w  --warn         warn about non-standard bc constructs\n",
+         "  -v  --version      print version information and exit\n");
+}
+
+
+void
+parse_args (argc, argv)
+     int argc;
+     char **argv;
+{
+  int optch;
+  int long_index;
+  file_node *temp;
+
+  /* Force getopt to initialize.  Depends on GNU getopt. */
+  optind = 0;
+
+  /* Parse the command line */
+  while (1)
+    {
+      optch = getopt_long (argc, argv, "chilqswv", long_options, &long_index);
+
+      if (optch == EOF)  /* End of arguments. */
+       break;
+
+      switch (optch)
+       {
+       case 0:    /* long option */
+         break;
+
+       case 'c':  /* compile only */
+         compile_only = TRUE;
+         break;
+
+       case 'h':  /* help */
+         usage(argv[0]);
+         exit (0);
+         break;
+
+       case 'i':  /* force interactive */
+         interactive = TRUE;
+         break;
+
+       case 'l':  /* math lib */
+         use_math = TRUE;
+         break;
+
+       case 'q':  /* quiet mode */
+         quiet = TRUE;
+         break;
+
+       case 's':  /* Non standard features give errors. */
+         std_only = TRUE;
+         break;
+
+       case 'v':  /* Print the version. */
+         show_bc_version ();
+         exit (0);
+         break;
+
+       case 'w':  /* Non standard features give warnings. */
+         warn_not_std = TRUE;
+         break;
+
+       default:
+         usage(argv[0]);
+         exit (1);
+       }
+    }
+
+  /* Add file names to a list of files to process. */
+  while (optind < argc)
+    {
+      temp = (file_node *) bc_malloc(sizeof(file_node));
+      temp->name = argv[optind];
+      temp->next = NULL;
+      if (last == NULL)
+       file_names = temp;
+      else
+       last->next = temp;
+      last = temp;
+      optind++;
+    }
+}
+
+/* The main program for bc. */
+int
+main (argc, argv)
+     int argc;
+     char *argv[];
+{
+  char *env_value;
+  char *env_argv[30];
+  int   env_argc;
+  
+  /* Initialize many variables. */
+  compile_only = FALSE;
+  use_math = FALSE;
+  warn_not_std = FALSE;
+  std_only = FALSE;
+  if (isatty(0) && isatty(1)) 
+    interactive = TRUE;
+  else
+    interactive = FALSE;
+  quiet = FALSE;
+  file_names = NULL;
+
+#ifdef HAVE_SETVBUF
+  /* attempt to simplify interaction with applications such as emacs */
+  (void) setvbuf(stdout, NULL, _IOLBF, 0);
+#endif
+
+  /* Environment arguments. */
+  env_value = getenv ("BC_ENV_ARGS");
+  if (env_value != NULL)
+    {
+      env_argc = 1;
+      env_argv[0] = "BC_ENV_ARGS";
+      while (*env_value != 0)
+       {
+         if (*env_value != ' ')
+           {
+             env_argv[env_argc++] = env_value;
+             while (*env_value != ' ' && *env_value != 0)
+               env_value++;
+             if (*env_value != 0)
+               {
+                 *env_value = 0;
+                 env_value++;
+               }
+           }
+         else
+           env_value++;
+       }
+      parse_args (env_argc, env_argv);
+    }
+
+  /* Command line arguments. */
+  parse_args (argc, argv);
+
+  /* Other environment processing. */
+  if (getenv ("POSIXLY_CORRECT") != NULL)
+    std_only = TRUE;
+
+  env_value = getenv ("BC_LINE_LENGTH");
+  if (env_value != NULL)
+    {
+      line_size = atoi (env_value);
+      if (line_size < 2)
+       line_size = 70;
+    }
+  else
+    line_size = 70;
+
+  /* Initialize the machine.  */
+  init_storage();
+  init_load();
+
+  /* Set up interrupts to print a message. */
+  if (interactive)
+    signal (SIGINT, use_quit);
+
+  /* Initialize the front end. */
+  init_tree();
+  init_gen ();
+  is_std_in = FALSE;
+  first_file = TRUE;
+  if (!open_new_file ())
+    exit (1);
+
+#if defined(LIBEDIT)
+  if (interactive) {
+    /* Enable libedit support. */
+    edit = el_init ("bc", stdin, stdout, stderr);
+    hist = history_init();
+    el_set (edit, EL_EDITOR, "emacs");
+    el_set (edit, EL_HIST, history, hist);
+    el_set (edit, EL_PROMPT, null_prompt);
+    el_source (edit, NULL);
+    history (hist, &histev, H_SETSIZE, INT_MAX);
+  }
+#endif
+
+#if defined(READLINE)
+  if (interactive) {
+    /* Readline support.  Set both application name and input file. */
+    rl_readline_name = "bc";
+    rl_instream = stdin;
+    using_history ();
+  }
+#endif
+
+  /* Do the parse. */
+  yyparse ();
+
+  /* End the compile only output with a newline. */
+  if (compile_only)
+    printf ("\n");
+
+  exit (0);
+}
+
+
+/* This is the function that opens all the files. 
+   It returns TRUE if the file was opened, otherwise
+   it returns FALSE. */
+
+int
+open_new_file ()
+{
+  FILE *new_file;
+  file_node *temp;
+
+  /* Set the line number. */
+  line_no = 1;
+
+  /* Check to see if we are done. */
+  if (is_std_in) return (FALSE);
+
+  /* Open the other files. */
+  if (use_math && first_file)
+    {
+      /* Load the code from a precompiled version of the math libarary. */
+      extern char *libmath[];
+      char **mstr;
+      char tmp;
+      /* These MUST be in the order of first mention of each function.
+        That is why "a" comes before "c" even though "a" is defined after
+        after "c".  "a" is used in "s"! */
+      tmp = lookup ("e", FUNCT);
+      tmp = lookup ("l", FUNCT);
+      tmp = lookup ("s", FUNCT);
+      tmp = lookup ("a", FUNCT);
+      tmp = lookup ("c", FUNCT);
+      tmp = lookup ("j", FUNCT);
+      mstr = libmath;
+      while (*mstr) {
+           load_code (*mstr);
+          mstr++;
+      }
+    }
+  
+  /* One of the argv values. */
+  if (file_names != NULL)
+    {
+      new_file = fopen (file_names->name, "r");
+      if (new_file != NULL)
+       {
+         new_yy_file (new_file);
+         temp = file_names;
+         file_name  = temp->name;
+         file_names = temp->next;
+         free (temp);
+         return TRUE;
+       }
+      fprintf (stderr, "File %s is unavailable.\n", file_names->name);
+      exit (1);
+    }
+  
+  /* If we fall through to here, we should return stdin. */
+  new_yy_file (stdin);
+  is_std_in = TRUE;
+  return TRUE;
+}
+
+
+/* Set yyin to the new file. */
+
+void
+new_yy_file (file)
+     FILE *file;
+{
+  if (!first_file) fclose (yyin);
+  yyin = file;
+  first_file = FALSE;
+}
+
+
+/* Message to use quit.  */
+
+void
+use_quit (sig)
+     int sig;
+{
+  printf ("\n(interrupt) use quit to exit.\n");
+  signal (SIGINT, use_quit);
+}
diff --git a/bc/proto.h b/bc/proto.h
new file mode 100644 (file)
index 0000000..1e7311f
--- /dev/null
@@ -0,0 +1,148 @@
+/* proto.h: Prototype function definitions for "external" functions. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+/* For the pc version using k&r ACK. (minix1.5 and earlier.) */
+#ifdef SHORTNAMES
+#define init_numbers i_numbers
+#define push_constant push__constant
+#define load_const in_load_const
+#define yy_get_next_buffer yyget_next_buffer
+#define yy_init_buffer yyinit_buffer
+#define yy_last_accepting_state yylast_accepting_state
+#define arglist1 arg1list
+#endif
+
+/* Include the standard library header files. */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/* Define the _PROTOTYPE macro if it is needed. */
+
+#ifndef _PROTOTYPE
+#ifdef __STDC__
+#define _PROTOTYPE(func, args) func args
+#else
+#define _PROTOTYPE(func, args) func()
+#endif
+#endif
+
+/* From execute.c */
+_PROTOTYPE(void stop_execution, (int));
+_PROTOTYPE(unsigned char byte, (program_counter *pc));
+_PROTOTYPE(void execute, (void));
+_PROTOTYPE(char prog_char, (void));
+_PROTOTYPE(char input_char, (void));
+_PROTOTYPE(void push_constant, (char (*in_char)(void), int conv_base));
+_PROTOTYPE(void push_b10_const, (program_counter *pc));
+_PROTOTYPE(void assign, (int c_code));
+
+/* From util.c */
+_PROTOTYPE(char *strcopyof, (char *str));
+_PROTOTYPE(arg_list *nextarg, (arg_list *args, int val, int is_var));
+_PROTOTYPE(char *arg_str, (arg_list *args));
+_PROTOTYPE(char *call_str, (arg_list *args));
+_PROTOTYPE(void free_args, (arg_list *args));
+_PROTOTYPE(void check_params, (arg_list *params, arg_list *autos));
+_PROTOTYPE(void init_gen, (void));
+_PROTOTYPE(void generate, (char *str));
+_PROTOTYPE(void run_code, (void));
+_PROTOTYPE(void out_char, (int ch));
+_PROTOTYPE(void out_schar, (int ch));
+_PROTOTYPE(id_rec *find_id, (id_rec *tree, char *id));
+_PROTOTYPE(int insert_id_rec, (id_rec **root, id_rec *new_id));
+_PROTOTYPE(void init_tree, (void));
+_PROTOTYPE(int lookup, (char *name, int namekind));
+_PROTOTYPE(char *bc_malloc, (int));
+_PROTOTYPE(void out_of_memory, (void));
+_PROTOTYPE(void welcome, (void));
+_PROTOTYPE(void warranty, (char *));
+_PROTOTYPE(void show_bc_version, (void));
+_PROTOTYPE(void limits, (void));
+_PROTOTYPE(void yyerror, (char *str ,...));
+_PROTOTYPE(void warn, (char *mesg ,...));
+_PROTOTYPE(void rt_error, (char *mesg ,...));
+_PROTOTYPE(void rt_warn, (char *mesg ,...));
+
+/* From load.c */
+_PROTOTYPE(void init_load, (void));
+_PROTOTYPE(void addbyte, (int byte));
+_PROTOTYPE(void def_label, (long lab));
+_PROTOTYPE(long long_val, (char **str));
+_PROTOTYPE(void load_code, (char *code));
+
+/* From main.c */
+_PROTOTYPE(int open_new_file, (void));
+_PROTOTYPE(void new_yy_file, (FILE *file));
+_PROTOTYPE(void use_quit, (int));
+
+/* From storage.c */
+_PROTOTYPE(void init_storage, (void));
+_PROTOTYPE(void more_functions, (void));
+_PROTOTYPE(void more_variables, (void));
+_PROTOTYPE(void more_arrays, (void));
+_PROTOTYPE(void clear_func, (int func ));
+_PROTOTYPE(int fpop, (void));
+_PROTOTYPE(void fpush, (int val ));
+_PROTOTYPE(void pop, (void));
+_PROTOTYPE(void push_copy, (bc_num num ));
+_PROTOTYPE(void push_num, (bc_num num ));
+_PROTOTYPE(char check_stack, (int depth ));
+_PROTOTYPE(bc_var *get_var, (int var_name ));
+_PROTOTYPE(bc_num *get_array_num, (int var_index, long index ));
+_PROTOTYPE(void store_var, (int var_name ));
+_PROTOTYPE(void store_array, (int var_name ));
+_PROTOTYPE(void load_var, (int var_name ));
+_PROTOTYPE(void load_array, (int var_name ));
+_PROTOTYPE(void decr_var, (int var_name ));
+_PROTOTYPE(void decr_array, (int var_name ));
+_PROTOTYPE(void incr_var, (int var_name ));
+_PROTOTYPE(void incr_array, (int var_name ));
+_PROTOTYPE(void auto_var, (int name ));
+_PROTOTYPE(void free_a_tree, (bc_array_node *root, int depth ));
+_PROTOTYPE(void pop_vars, (arg_list *list ));
+_PROTOTYPE(void process_params, (program_counter *pc, int func ));
+
+/* For the scanner and parser.... */
+_PROTOTYPE(int yyparse, (void));
+_PROTOTYPE(int yylex, (void)); 
+
+#if defined(LIBEDIT)
+/* The *?*&^ prompt function */
+_PROTOTYPE(char *null_prompt, (EditLine *));
+#endif
+
+/* Other things... */
+#ifndef HAVE_UNISTD_H
+_PROTOTYPE (int getopt, (int, char *[], CONST char *));
+#endif
diff --git a/bc/sbc.y b/bc/sbc.y
new file mode 100644 (file)
index 0000000..b1ff1d1
--- /dev/null
+++ b/bc/sbc.y
@@ -0,0 +1,448 @@
+%{
+/* sbc.y: A POSIX bc processor written for minix with no extensions.  */
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"     /* To get the global variables. */
+#include "proto.h"
+%}
+
+%start program
+
+%union {
+       char *s_value;
+       char  c_value;
+       int   i_value;
+       arg_list *a_value;
+       }
+
+%token <i_value> ENDOFLINE AND OR NOT
+%token <s_value> STRING NAME NUMBER
+/*     '-', '+' are tokens themselves          */
+%token <c_value> ASSIGN_OP
+/*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
+%token <s_value> REL_OP
+/*     '==', '<=', '>=', '!=', '<', '>'        */
+%token <c_value> INCR_DECR
+/*     '++', '--'                              */
+%token <i_value> Define    Break    Quit    Length
+/*     'define', 'break', 'quit', 'length'     */
+%token <i_value> Return    For    If    While    Sqrt  Else
+/*     'return', 'for', 'if', 'while', 'sqrt',  'else'         */
+%token <i_value> Scale    Ibase    Obase    Auto  Read
+/*     'scale', 'ibase', 'obase', 'auto', 'read'       */
+%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
+/*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'  */
+
+/* The types of all other non-terminals. */
+%type <i_value> expression named_expression return_expression
+%type <a_value> opt_parameter_list parameter_list opt_auto_define_list
+%type <a_value> define_list opt_argument_list argument_list
+%type <i_value> program input_item semicolon_list statement_list
+%type <i_value> statement_or_error statement function relational_expression 
+
+/* precedence */
+%nonassoc REL_OP
+%right ASSIGN_OP
+%left '+' '-'
+%left '*' '/' '%'
+%right '^'
+%nonassoc UNARY_MINUS
+%nonassoc INCR_DECR
+
+%%
+program                        : /* empty */
+                           {
+                             $$ = 0;
+                             std_only = TRUE;
+                             if (interactive)
+                               {
+                                 printf ("s%s\n", BC_VERSION);
+                                 welcome();
+                               }
+                           }
+                       | program input_item
+                       ;
+input_item             : semicolon_list ENDOFLINE
+                           { run_code(); }
+                       | function
+                           { run_code(); }
+                       | error ENDOFLINE
+                           {
+                             yyerrok; 
+                             init_gen() ;
+                           }
+                       ;
+semicolon_list         : /* empty */
+                           { $$ = 0; }
+                       | statement_or_error
+                       | semicolon_list ';' statement_or_error
+                       | semicolon_list ';'
+                       ;
+statement_list         : /* empty */
+                           { $$ = 0; }
+                       | statement
+                       | statement_list ENDOFLINE
+                       | statement_list ENDOFLINE statement
+                       | statement_list ';'
+                       | statement_list ';' statement
+                       ;
+statement_or_error     : statement
+                       | error statement
+                           { $$ = $2; }
+                       ;
+statement              : Warranty
+                           { warranty("s"); }
+                       | expression
+                           {
+                             if ($1 & 1)
+                               generate ("W");
+                             else
+                               generate ("p");
+                           }
+                       | STRING
+                           {
+                             $$ = 0;
+                             generate ("w");
+                             generate ($1);
+                             free ($1);
+                           }
+                       | Break
+                           {
+                             if (break_label == 0)
+                               yyerror ("Break outside a for/while");
+                             else
+                               {
+                                 sprintf (genstr, "J%1d:", break_label);
+                                 generate (genstr);
+                               }
+                           }
+                       | Quit
+                           { exit(0); }
+                       | Return
+                           { generate ("0R"); }
+                       | Return '(' return_expression ')'
+                           { generate ("R"); }
+                       | For 
+                           {
+                             $1 = break_label; 
+                             break_label = next_label++;
+                           }
+                         '(' expression ';'
+                           {
+                             $4 = next_label++;
+                             sprintf (genstr, "pN%1d:", $4);
+                             generate (genstr);
+                           }
+                         relational_expression ';'
+                           {
+                             $7 = next_label++;
+                             sprintf (genstr, "B%1d:J%1d:", $7, break_label);
+                             generate (genstr);
+                             $<i_value>$ = next_label++;
+                             sprintf (genstr, "N%1d:", $<i_value>$);
+                             generate (genstr);
+                           }
+                         expression ')'
+                           {
+                             sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
+                             generate (genstr);
+                           }
+                         statement
+                           {
+                             sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
+                                      break_label);
+                             generate (genstr);
+                             break_label = $1;
+                           }
+                       | If '(' relational_expression ')' 
+                           {
+                             $3 = next_label++;
+                             sprintf (genstr, "Z%1d:", $3);
+                             generate (genstr);
+                           }
+                         statement
+                           {
+                             sprintf (genstr, "N%1d:", $3); 
+                             generate (genstr);
+                           }
+                       | While 
+                           {
+                             $1 = next_label++;
+                             sprintf (genstr, "N%1d:", $1);
+                             generate (genstr);
+                           }
+                       '(' relational_expression 
+                           {
+                             $4 = break_label; 
+                             break_label = next_label++;
+                             sprintf (genstr, "Z%1d:", break_label);
+                             generate (genstr);
+                           }
+                       ')' statement
+                           {
+                             sprintf (genstr, "J%1d:N%1d:", $1, break_label);
+                             generate (genstr);
+                             break_label = $4;
+                           }
+                       | '{' statement_list '}'
+                           { $$ = 0; }
+                       ;
+function               : Define NAME '(' opt_parameter_list ')' '{'
+                                 ENDOFLINE opt_auto_define_list 
+                           {
+                             check_params ($4,$8);
+                             sprintf (genstr, "F%d,%s.%s[", lookup($2,FUNCT),
+                                      arg_str ($4), arg_str ($8));
+                             generate (genstr);
+                             free_args ($4);
+                             free_args ($8);
+                             $1 = next_label;
+                             next_label = 0;
+                           }
+                         statement_list ENDOFLINE '}'
+                           {
+                             generate ("0R]");
+                             next_label = $1;
+                           }
+                       ;
+opt_parameter_list     : /* empty */ 
+                           { $$ = NULL; }
+                       | parameter_list
+                       ;
+parameter_list                 : NAME
+                           { $$ = nextarg (NULL, lookup($1,SIMPLE), FALSE); }
+                       | define_list ',' NAME
+                           { $$ = nextarg ($1, lookup($3,SIMPLE), FALSE); }
+                       ;
+opt_auto_define_list   : /* empty */ 
+                           { $$ = NULL; }
+                       | Auto define_list ENDOFLINE
+                           { $$ = $2; } 
+                       | Auto define_list ';'
+                           { $$ = $2; } 
+                       ;
+define_list            : NAME
+                           { $$ = nextarg (NULL, lookup($1,SIMPLE), FALSE); }
+                       | NAME '[' ']'
+                           { $$ = nextarg (NULL, lookup($1,ARRAY), FALSE); }
+                       | define_list ',' NAME
+                           { $$ = nextarg ($1, lookup($3,SIMPLE), FALSE); }
+                       | define_list ',' NAME '[' ']'
+                           { $$ = nextarg ($1, lookup($3,ARRAY), FALSE); }
+                       ;
+opt_argument_list      : /* empty */
+                           { $$ = NULL; }
+                       | argument_list
+                       ;
+argument_list          : expression
+                           { $$ = nextarg (NULL,0, FALSE); }
+                       | argument_list ',' expression
+                           { $$ = nextarg ($1,0, FALSE); }
+                       ;
+relational_expression  : expression
+                           { $$ = 0; }
+                       | expression REL_OP expression
+                           {
+                             $$ = 0;
+                             switch (*($2))
+                               {
+                               case '=':
+                                 generate ("=");
+                                 break;
+                               case '!':
+                                 generate ("#");
+                                 break;
+                               case '<':
+                                 if ($2[1] == '=')
+                                   generate ("{");
+                                 else
+                                   generate ("<");
+                                 break;
+                               case '>':
+                                 if ($2[1] == '=')
+                                   generate ("}");
+                                 else
+                                   generate (">");
+                                 break;
+                               }
+                           }
+                       ;
+return_expression      : /* empty */
+                           {
+                             $$ = 0;
+                             generate ("0");
+                           }
+                       | expression
+                       ;
+expression             : named_expression ASSIGN_OP 
+                           {
+                             if ($2 != '=')
+                               {
+                                 if ($1 < 0)
+                                   sprintf (genstr, "DL%d:", -$1);
+                                 else
+                                   sprintf (genstr, "l%d:", $1);
+                                 generate (genstr);
+                               }
+                           }
+                         expression
+                           {
+                             $$ = 0;
+                             if ($2 != '=')
+                               {
+                                 sprintf (genstr, "%c", $2);
+                                 generate (genstr);
+                               }
+                             if ($1 < 0)
+                               sprintf (genstr, "S%d:", -$1);
+                             else
+                               sprintf (genstr, "s%d:", $1);
+                             generate (genstr);
+                           }
+                       | expression '+' expression
+                           { generate ("+"); }
+                       | expression '-' expression
+                           { generate ("-"); }
+                       | expression '*' expression
+                           { generate ("*"); }
+                       | expression '/' expression
+                           { generate ("/"); }
+                       | expression '%' expression
+                           { generate ("%"); }
+                       | expression '^' expression
+                           { generate ("^"); }
+                       | '-' expression           %prec UNARY_MINUS
+                           { generate ("n"); $$ = 1;}
+                       | named_expression
+                           {
+                             $$ = 1;
+                             if ($1 < 0)
+                               sprintf (genstr, "L%d:", -$1);
+                             else
+                               sprintf (genstr, "l%d:", $1);
+                             generate (genstr);
+                           }
+                       | NUMBER
+                           {
+                             int len = strlen($1);
+                             $$ = 1;
+                             if (len == 1 && *$1 == '0')
+                               generate ("0");
+                             else
+                               {
+                                 if (len == 1 && *$1 == '1')
+                                   generate ("1");
+                                 else
+                                   {
+                                     generate ("K");
+                                     generate ($1);
+                                     generate (":");
+                                   }
+                                 free ($1);
+                               }
+                           }
+                       | '(' expression ')'
+                           { $$ = 1; }
+                       | NAME '(' opt_argument_list ')'
+                           {
+                             $$ = 1;
+                             if ($3 != NULL)
+                               { 
+                                 sprintf (genstr, "C%d,%s:", lookup($1,FUNCT),
+                                          arg_str ($3));
+                                 free_args ($3);
+                               }
+                             else
+                                 sprintf (genstr, "C%d:", lookup($1,FUNCT));
+                             generate (genstr);
+                           }
+                       | INCR_DECR named_expression
+                           {
+                             $$ = 1;
+                             if ($2 < 0)
+                               {
+                                 if ($1 == '+')
+                                   sprintf (genstr, "DA%d:L%d:", -$2, -$2);
+                                 else
+                                   sprintf (genstr, "DM%d:L%d:", -$2, -$2);
+                               }
+                             else
+                               {
+                                 if ($1 == '+')
+                                   sprintf (genstr, "i%d:l%d:", $2, $2);
+                                 else
+                                   sprintf (genstr, "d%d:l%d:", $2, $2);
+                               }
+                             generate (genstr);
+                           }
+                       | named_expression INCR_DECR
+                           {
+                             $$ = 1;
+                             if ($1 < 0)
+                               {
+                                 sprintf (genstr, "DL%d:x", -$1);
+                                 generate (genstr); 
+                                 if ($2 == '+')
+                                   sprintf (genstr, "A%d:", -$1);
+                                 else
+                                   sprintf (genstr, "M%d:", -$1);
+                               }
+                             else
+                               {
+                                 sprintf (genstr, "l%d:", $1);
+                                 generate (genstr);
+                                 if ($2 == '+')
+                                   sprintf (genstr, "i%d:", $1);
+                                 else
+                                   sprintf (genstr, "d%d:", $1);
+                               }
+                             generate (genstr);
+                           }
+                       | Length '(' expression ')'
+                           { generate ("cL"); $$ = 1;}
+                       | Sqrt '(' expression ')'
+                           { generate ("cR"); $$ = 1;}
+                       | Scale '(' expression ')'
+                           { generate ("cS"); $$ = 1;}
+                       ;
+named_expression       : NAME
+                           { $$ = lookup($1,SIMPLE); }
+                       | NAME '[' expression ']'
+                           { $$ = lookup($1,ARRAY); }
+                       | Ibase
+                           { $$ = 0; }
+                       | Obase
+                           { $$ = 1; }
+                       | Scale
+                           { $$ = 2; }
+                       ;
+
+%%
diff --git a/bc/scan.c b/bc/scan.c
new file mode 100644 (file)
index 0000000..8d9c92d
--- /dev/null
+++ b/bc/scan.c
@@ -0,0 +1,2259 @@
+/* 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>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.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)
+
+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 44
+#define YY_END_OF_BUFFER 45
+static yyconst short int yy_accept[298] =
+    {   0,
+        0,    0,    2,    2,   45,   43,   38,   36,   30,   43,
+        1,   31,   43,   27,   31,   27,   27,   26,   31,   42,
+       34,   32,   34,   43,   27,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,   43,    2,    2,    3,    2,    2,    1,    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,   38,
+       34,    0,   41,   32,   28,   35,   42,    0,   39,   42,
+       42,    0,   33,   37,   40,   40,   40,   40,   40,   40,
+
+       40,   40,   40,   40,   10,   40,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   29,    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,   42,    0,    0,   42,    0,
+       40,   40,   40,   40,   40,    9,   40,   40,   40,   40,
+       40,   40,   40,   40,   40,   40,   40,   40,   40,   40,
+       40,    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,   16,   40,   40,   40,
+       17,   19,   40,   40,   20,   40,   40,   40,   40,    6,
+       18,   40,   40,   12,   40,   40,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    5,   40,   40,   40,
+       14,   40,   40,   15,   24,   40,   13,   40,   11,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,   40,    4,   40,    7,   25,    8,   40,    2,
+        2,    2,    2,    2,    2,    2,   40,   21,   40,    2,
+        2,    2,   23,   22,    2,    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,    5,    6,    1,    7,    8,    1,    9,
+       10,   11,   12,   13,   14,   15,   16,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,    1,   18,   19,
+       20,   21,    1,    1,   22,   22,   22,   22,   22,   22,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+       23,   24,   25,   26,   27,    1,   28,   29,   30,   31,
+
+       32,   33,   34,   35,   36,   37,   38,   39,   40,   41,
+       42,   43,   44,   45,   46,   47,   48,   37,   49,   37,
+       50,   37,   51,   52,   53,    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,    1
+    } ;
+
+static yyconst int yy_meta[54] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    3,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        1,    1,    1
+    } ;
+
+static yyconst short int yy_base[302] =
+    {   0,
+        0,    0,   53,    0,  525,  526,  522,  526,  503,  517,
+      526,  501,  512,  526,  499,   95,   94,   94,   99,  105,
+      498,  114,  497,  513,  495,  466,  468,  470,  479,  471,
+      467,    0,   81,  102,  105,  479,  462,  458,  473,   94,
+      104,  452,    0,  501,  526,  482,  139,    0,  481,  492,
+        0,  479,  131,  132,  131,  125,  132,  478,  150,  477,
+      493,  475,  160,  115,  117,  126,  130,  125,  446,  183,
+      184,  186,  187,  123,  445,  180,  185,  192,  440,  489,
+      526,  485,  526,  526,  526,  526,  158,  486,  526,  162,
+      221,  485,  526,  526,    0,  440,  454,  444,  451,  437,
+
+      437,  442,  434,  451,    0,  432,  436,  436,  447,  438,
+      437,  195,  444,  426,  425,  433,  526,    0,  466,    0,
+      178,    0,    0,    0,    0,  222,  464,    0,  230,  233,
+      463,    0,  417,   65,  189,  208,  193,  205,  213,  220,
+      214,  235,  416,  218,  224,  227,  241,  234,  237,  243,
+      246,  231,  232,  245,    0,  275,  460,  278,  279,  459,
+      419,  432,  412,  422,  425,    0,  409,  408,  408,  406,
+      418,  415,  404,  408,  401,  416,  398,  406,  397,  398,
+      403,  287,  438,  288,  437,  182,  250,  239,  270,  275,
+      391,  266,  268,  271,  273,  274,  288,  279,  285,  281,
+
+      299,  390,  292,  287,  293,  298,    0,  399,  400,  394,
+        0,    0,  392,  401,    0,  385,  384,  398,  382,    0,
+        0,  383,  395,    0,  398,  393,  376,  294,  303,  302,
+      375,  374,  306,  312,  373,  305,  308,  313,  310,  372,
+      371,  314,  317,  370,  335,  332,    0,  376,  384,  370,
+        0,  379,  367,    0,    0,  371,    0,  370,    0,  362,
+      325,  336,  322,  361,  137,  323,  360,  359,  331,  358,
+      333,  357,  356,    0,  353,    0,    0,    0,  355,  349,
+      343,  327,  342,  340,  334,  338,  346,    0,  238,  344,
+      236,  339,    0,    0,  177,  102,  526,  392,  120,  395,
+
+      398
+    } ;
+
+static yyconst short int yy_def[302] =
+    {   0,
+      297,    1,  297,    3,  297,  297,  297,  297,  297,  298,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  297,  300,  300,  297,  300,  301,  300,  300,  300,
+      300,  300,  300,  300,  300,  300,  300,  300,  300,  300,
+      300,  300,  300,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,  300,  297,
+      297,  298,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  299,  299,  299,  299,  299,  299,
+
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  297,  300,  300,  300,
+      301,  300,  300,  300,  300,  300,  300,  300,  300,  300,
+      300,  300,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,  300,  297,  297,  297,  297,  297,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  300,  300,  300,  300,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+
+       63,   63,   63,   63,   63,   63,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,  299,  299,  299,  299,  299,  299,  299,   63,
+       63,   63,   63,   63,   63,   63,  299,  299,  299,   63,
+       63,   63,  299,  299,   63,   63,    0,  297,  297,  297,
+
+      297
+    } ;
+
+static yyconst short int yy_nxt[580] =
+    {   0,
+        6,    7,    8,    9,   10,   11,   12,   13,   14,   14,
+       15,   16,   14,   17,   18,   19,   20,   14,   21,   22,
+       23,   20,   14,   24,   14,   25,    6,   26,   27,   28,
+       29,   30,   31,   32,   33,   34,   32,   32,   35,   32,
+       32,   36,   37,   38,   39,   40,   32,   32,   41,   32,
+       14,   42,   14,   43,   44,   45,   46,   47,   48,   49,
+       50,   51,   51,   52,   53,   51,   54,   55,   56,   57,
+       51,   58,   59,   60,   57,   51,   61,   51,   62,   43,
+       63,   64,   65,   66,   67,   68,   69,   70,   71,   69,
+       69,   72,   69,   69,   73,   74,   75,   76,   77,   69,
+
+       69,   78,   69,   51,   79,   51,   86,   86,  102,   89,
+       87,  186,  133,   84,   84,   87,  103,   88,   84,   90,
+       93,   91,   95,  113,   93,   93,   91,   93,   92,   93,
+      104,  115,  106,   81,  105,  128,  107,  114,  116,   93,
+      108,   82,  125,  122,  123,  125,  129,  126,  130,  133,
+      123,  123,  126,  130,  127,  131,  132,  137,  136,  135,
+      132,  132,  133,  132,  133,  132,  139,  148,  138,  120,
+      133,  283,  133,  133,  156,  132,  133,  133,  159,  156,
+       82,  157,  122,  159,  133,  160,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+
+      133,  133,  133,  133,  133,  133,  133,  134,  133,  133,
+      140,  150,  142,  144,  151,  147,  143,  145,  141,  153,
+      187,  146,  176,  227,  133,  189,  154,  133,  152,  133,
+      133,  133,  133,  133,  133,   90,  133,   91,  182,  133,
+      133,  177,   91,  182,   92,  183,  184,  129,  188,  130,
+      190,  184,  133,  185,  130,  133,  131,  191,  192,  193,
+      133,  133,  194,  195,  196,  133,  197,  133,  198,  199,
+      201,  133,  200,  203,  133,  204,  205,  228,  133,  133,
+      206,  133,  133,  133,  133,  229,  133,  294,  133,  202,
+      133,  156,  133,  133,   87,  159,  156,  133,  157,   87,
+
+      159,   88,  160,  182,  184,  230,  231,  236,  182,  184,
+      183,  185,  232,  133,  233,  133,  234,  133,  133,  235,
+      133,  133,  133,  237,  238,  239,  133,  240,  133,  241,
+      243,  260,  133,  244,  133,  133,  246,  245,  261,  133,
+      133,  133,  262,  264,  267,  133,  133,  263,  270,  133,
+      133,  265,  133,  133,  266,  133,  268,  133,  269,  133,
+      133,  133,  271,  272,  133,  280,  282,  281,  284,  133,
+      133,  285,  133,  286,  133,  295,  291,  293,  133,  133,
+      133,  133,  133,  133,  292,  133,  133,  133,  296,  133,
+      133,  133,   82,   82,   82,  118,  290,  118,  121,  121,
+
+      121,  289,  288,  287,  133,  133,  133,  133,  133,  133,
+      279,  278,  277,  276,  275,  274,  273,  133,  133,  133,
+      133,  133,  133,  133,  259,  258,  257,  256,  255,  254,
+      253,  252,  251,  250,  249,  248,  247,  242,  133,  159,
+      156,  226,  225,  224,  223,  222,  221,  220,  219,  218,
+      217,  216,  215,  214,  213,  212,  211,  210,  209,  208,
+      207,  159,  156,  133,  133,   91,  158,  119,  181,  180,
+      179,  178,  175,  174,  173,  172,  171,  170,  169,  168,
+      167,  166,  165,  164,  163,  162,  161,   91,  158,   83,
+       80,  155,  149,  133,  123,   94,  120,  120,  123,  124,
+
+      123,  120,  119,  117,  112,  111,  110,  109,  101,  100,
+       99,   98,   97,   96,   84,   94,   81,   81,   84,   85,
+       84,   83,   81,   80,  297,    5,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297
+    } ;
+
+static yyconst short int yy_chk[580] =
+    {   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,    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,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+
+        3,    3,    3,    3,    3,    3,   16,   17,   33,   19,
+       18,  134,  134,   17,   16,   18,   33,   18,   19,   20,
+       22,   20,  299,   40,   22,   22,   20,   22,   20,   22,
+       34,   41,   35,   22,   34,   56,   35,   40,   41,   22,
+       35,   47,   53,   47,   56,   54,   57,   55,   57,  296,
+       53,   54,   55,   57,   55,   57,   59,   66,   65,   64,
+       59,   59,   64,   59,   65,   59,   68,   74,   67,   59,
+       74,  265,   68,   66,   87,   59,   63,   67,   90,   87,
+      121,   87,  121,   90,  265,   90,   63,   63,   63,   63,
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+
+       63,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       70,   76,   71,   72,   77,   73,   71,   72,   70,   78,
+      135,   72,  112,  186,  295,  137,   78,   76,   77,  186,
+       70,   71,   77,   72,   73,   91,  135,   91,  126,   78,
+      137,  112,   91,  126,   91,  126,  129,  130,  136,  130,
+      138,  129,  138,  129,  130,  136,  130,  139,  140,  141,
+      139,  141,  142,  144,  145,  144,  146,  140,  147,  148,
+      150,  145,  149,  151,  146,  152,  153,  187,  152,  153,
+      154,  148,  142,  291,  149,  188,  188,  289,  147,  150,
+      150,  156,  154,  151,  158,  159,  156,  187,  156,  158,
+
+      159,  158,  159,  182,  184,  189,  190,  196,  182,  184,
+      182,  184,  192,  192,  193,  193,  194,  189,  194,  195,
+      195,  196,  190,  197,  198,  199,  198,  200,  200,  201,
+      203,  228,  199,  204,  204,  197,  206,  205,  229,  203,
+      205,  228,  230,  234,  238,  206,  201,  233,  243,  230,
+      229,  236,  236,  233,  237,  237,  239,  239,  242,  234,
+      238,  242,  245,  246,  243,  261,  263,  262,  266,  263,
+      266,  269,  261,  271,  282,  290,  282,  287,  269,  246,
+      271,  285,  245,  262,  286,  286,  292,  284,  292,  283,
+      281,  290,  298,  298,  298,  300,  280,  300,  301,  301,
+
+      301,  279,  275,  273,  272,  270,  268,  267,  264,  260,
+      258,  256,  253,  252,  250,  249,  248,  244,  241,  240,
+      235,  232,  231,  227,  226,  225,  223,  222,  219,  218,
+      217,  216,  214,  213,  210,  209,  208,  202,  191,  185,
+      183,  181,  180,  179,  178,  177,  176,  175,  174,  173,
+      172,  171,  170,  169,  168,  167,  165,  164,  163,  162,
+      161,  160,  157,  143,  133,  131,  127,  119,  116,  115,
+      114,  113,  111,  110,  109,  108,  107,  106,  104,  103,
+      102,  101,  100,   99,   98,   97,   96,   92,   88,   82,
+       80,   79,   75,   69,   62,   61,   60,   58,   52,   50,
+
+       49,   46,   44,   42,   39,   38,   37,   36,   31,   30,
+       29,   28,   27,   26,   25,   24,   23,   21,   15,   13,
+       12,   10,    9,    7,    5,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297,  297,
+      297,  297,  297,  297,  297,  297,  297,  297,  297
+    } ;
+
+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 "scan.l"
+#define INITIAL 0
+#line 2 "scan.l"
+/* scan.l: the (f)lex description file for the scanner. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "bc.h"
+#include "global.h"
+#include "proto.h"
+#include <errno.h>
+
+/* Using flex, we can ask for a smaller input buffer.  With lex, this
+   does nothing! */
+
+#ifdef SMALL_BUF
+#undef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 512
+#endif
+
+/* Force . as last for now. */
+#define DOT_IS_LAST
+
+/* We want to define our own yywrap. */
+#undef yywrap
+_PROTOTYPE(int yywrap, (void));
+
+#if defined(LIBEDIT)
+/* Support for the BSD libedit with history for
+   nicer input on the interactive part of input. */
+
+#include <histedit.h>
+
+/* Have input call the following function. */
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+               bcel_input((char *)buf, &result, max_size)
+
+/* Variables to help interface editline with bc. */
+static const char *bcel_line = (char *)NULL;
+static int   bcel_len = 0;
+
+
+/* Required to get rid of that ugly ? default prompt! */
+char *
+null_prompt (EditLine *el)
+{
+  return "";
+}
+
+
+/* bcel_input puts upto MAX characters into BUF with the number put in
+   BUF placed in *RESULT.  If the yy input file is the same as
+   stdin, use editline.  Otherwise, just read it.
+*/
+
+static void
+bcel_input (buf, result, max)
+       char *buf;
+       int  *result;
+       int   max;
+{
+  if (!edit || yyin != stdin)
+    {
+      while ( (*result = read( fileno(yyin), buf, max )) < 0 )
+        if (errno != EINTR)
+         {
+           yyerror( "read() in flex scanner failed" );
+           exit (1);
+         }
+      return;
+    }
+
+  /* Do we need a new string? */
+  if (bcel_len == 0)
+    {
+      bcel_line = el_gets(edit, &bcel_len);
+      if (bcel_line == NULL) {
+       /* end of file */
+       *result = 0;
+       bcel_len = 0;
+       return;
+      }
+      if (bcel_len != 0)
+       history (hist, &histev, H_ENTER, bcel_line); 
+      fflush (stdout);
+    }
+
+  if (bcel_len <= max)
+    {
+      strncpy (buf, bcel_line, bcel_len);
+      *result = bcel_len;
+      bcel_len = 0;
+    }
+  else
+    {
+      strncpy (buf, bcel_line, max);
+      *result = max;
+      bcel_line += max;
+      bcel_len -= max;
+    }
+}
+#endif
+
+#ifdef READLINE
+/* Support for the readline and history libraries.  This allows
+   nicer input on the interactive part of input. */
+
+/* Have input call the following function. */
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+               rl_input((char *)buf, &result, max_size)
+
+/* Variables to help interface readline with bc. */
+static char *rl_line = (char *)NULL;
+static char *rl_start = (char *)NULL;
+static int   rl_len = 0;
+
+/* Definitions for readline access. */
+extern FILE *rl_instream;
+_PROTOTYPE(char *readline, (char *));
+
+/* rl_input puts upto MAX characters into BUF with the number put in
+   BUF placed in *RESULT.  If the yy input file is the same as
+   rl_instream (stdin), use readline.  Otherwise, just read it.
+*/
+
+static void
+rl_input (buf, result, max)
+       char *buf;
+       int  *result;
+       int   max;
+{
+  if (yyin != rl_instream)
+    {
+      while ( (*result = read( fileno(yyin), buf, max )) < 0 )
+        if (errno != EINTR)
+         {
+           yyerror( "read() in flex scanner failed" );
+           exit (1);
+         }
+      return;
+    }
+
+  /* Do we need a new string? */
+  if (rl_len == 0)
+    {
+      if (rl_start)
+       free(rl_start);
+      rl_start = readline ("");
+      if (rl_start == NULL) {
+       /* end of file */
+       *result = 0;
+       rl_len = 0;
+       return;
+      }
+      rl_line = rl_start;
+      rl_len = strlen (rl_line)+1;
+      if (rl_len != 1)
+       add_history (rl_line); 
+      rl_line[rl_len-1] = '\n';
+      fflush (stdout);
+    }
+
+  if (rl_len <= max)
+    {
+      strncpy (buf, rl_line, rl_len);
+      *result = rl_len;
+      rl_len = 0;
+    }
+  else
+    {
+      strncpy (buf, rl_line, max);
+      *result = max;
+      rl_line += max;
+      rl_len -= max;
+    }
+}
+#endif
+
+#if !defined(READLINE) && !defined(LIBEDIT)
+
+/* MINIX returns from read with < 0 if SIGINT is  encountered.
+   In flex, we can redefine YY_INPUT to the following.  In lex, this
+   does nothing! */
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+           if (errno != EINTR) \
+               YY_FATAL_ERROR( "read() in flex scanner failed" );
+#endif
+
+#define slcomment 1
+
+#line 809 "lex.yy.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, *yy_bp;
+       register int yy_act;
+
+#line 222 "scan.l"
+
+#line 962 "lex.yy.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 >= 298 )
+                                       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] != 526 );
+
+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 223 "scan.l"
+{
+                 if (!std_only)
+                   BEGIN(slcomment);
+                 else
+                   yyerror ("illegal character: #");
+               }
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 229 "scan.l"
+{ BEGIN(INITIAL); }
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 230 "scan.l"
+{ line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 231 "scan.l"
+return(Define);
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 232 "scan.l"
+return(Break);
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 233 "scan.l"
+return(Quit);
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 234 "scan.l"
+return(Length);
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 235 "scan.l"
+return(Return);
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 236 "scan.l"
+return(For);
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 237 "scan.l"
+return(If);
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 238 "scan.l"
+return(While);
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 239 "scan.l"
+return(Sqrt);
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 240 "scan.l"
+return(Scale);
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 241 "scan.l"
+return(Ibase);
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 242 "scan.l"
+return(Obase);
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 243 "scan.l"
+return(Auto);
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 244 "scan.l"
+return(Else);
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 245 "scan.l"
+return(Read);
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 246 "scan.l"
+return(Halt);
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 247 "scan.l"
+return(Last);
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 248 "scan.l"
+{
+#if defined(READLINE) || defined(LIBEDIT)
+         return(HistoryVar);
+#else
+         yylval.s_value = strcopyof(yytext); return(NAME);
+#endif
+       }
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 256 "scan.l"
+return(Warranty);
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 257 "scan.l"
+return(Continue);
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 258 "scan.l"
+return(Print);
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 259 "scan.l"
+return(Limits);
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 260 "scan.l"
+{
+#ifdef DOT_IS_LAST
+       return(Last);
+#else
+       yyerror ("illegal character: %s",yytext);
+#endif
+    }
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 267 "scan.l"
+{ yylval.c_value = yytext[0]; 
+                                             return((int)yytext[0]); }
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 269 "scan.l"
+{ return(AND); }
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 270 "scan.l"
+{ return(OR); }
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 271 "scan.l"
+{ return(NOT); }
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 272 "scan.l"
+{ yylval.c_value = yytext[0]; return((int)yytext[0]); }
+       YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 273 "scan.l"
+{ yylval.c_value = yytext[0]; return(ASSIGN_OP); }
+       YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 274 "scan.l"
+{ 
+#ifdef OLD_EQ_OP
+                        char warn_save;
+                        warn_save = warn_not_std;
+                        warn_not_std = TRUE;
+                        warn ("Old fashioned =<op>");
+                        warn_not_std = warn_save;
+                        yylval.c_value = yytext[1];
+#else
+                        yylval.c_value = '=';
+                        yyless (1);
+#endif
+                        return(ASSIGN_OP);
+                      }
+       YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 288 "scan.l"
+{ yylval.s_value = strcopyof(yytext); return(REL_OP); }
+       YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 289 "scan.l"
+{ yylval.c_value = yytext[0]; return(INCR_DECR); }
+       YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 290 "scan.l"
+{ line_no++; return(ENDOFLINE); }
+       YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 291 "scan.l"
+{  line_no++;  /* ignore a "quoted" newline */ }
+       YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 292 "scan.l"
+{ /* ignore spaces and tabs */ }
+       YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 293 "scan.l"
+{
+       int c;
+
+       for (;;)
+         {
+           while ( ((c=input()) != '*') && (c != EOF)) 
+             /* eat it */
+             if (c == '\n') line_no++;
+           if (c == '*')
+             {
+               while ( (c=input()) == '*') /* eat it*/;
+               if (c == '/') break; /* at end of comment */
+               if (c == '\n') line_no++;
+             }
+           if (c == EOF)
+             {
+               fprintf (stderr,"EOF encountered in a comment.\n");
+               break;
+             }
+         }
+      }
+       YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 314 "scan.l"
+{ yylval.s_value = strcopyof(yytext); return(NAME); }
+       YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 315 "scan.l"
+{
+             unsigned char *look;
+             int count = 0;
+             yylval.s_value = strcopyof(yytext);
+             for (look = yytext; *look != 0; look++)
+               {
+                 if (*look == '\n') line_no++;
+                 if (*look == '"')  count++;
+               }
+             if (count != 2) yyerror ("NUL character in string.");
+             return(STRING);
+           }
+       YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 327 "scan.l"
+{
+             unsigned char *src, *dst;
+             int len;
+             /* remove a trailing decimal point. */
+             len = strlen(yytext);
+             if (yytext[len-1] == '.')
+               yytext[len-1] = 0;
+             /* remove leading zeros. */
+             src = yytext;
+             dst = yytext;
+             while (*src == '0') src++;
+             if (*src == 0) src--;
+             /* Copy strings removing the newlines. */
+             while (*src != 0)
+               {
+                 if (*src == '\\')
+                   {
+                     src++; src++;
+                     line_no++;
+                   }
+                 else
+                   *dst++ = *src++;
+               }
+             *dst = 0;
+             yylval.s_value = strcopyof(yytext); 
+             return(NUMBER);
+           }
+       YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 354 "scan.l"
+{
+         if (yytext[0] < ' ')
+           yyerror ("illegal character: ^%c",yytext[0] + '@');
+         else
+           if (yytext[0] > '~')
+             yyerror ("illegal character: \\%03o", (int) yytext[0]);
+           else
+             yyerror ("illegal character: %s",yytext);
+       }
+       YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 363 "scan.l"
+ECHO;
+       YY_BREAK
+#line 1361 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(slcomment):
+       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 >= 298 )
+                               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 >= 298 )
+                       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 == 297);
+
+       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 );
+       }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#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 363 "scan.l"
+
+
+
+
+/* This is the way to get multiple files input into lex. */
+
+int
+yywrap()
+{
+  if (!open_new_file ()) return (1);   /* EOF on standard in. */
+  return (0);                          /* We have more input. */
+}
diff --git a/bc/scan.l b/bc/scan.l
new file mode 100644 (file)
index 0000000..38aa2f0
--- /dev/null
+++ b/bc/scan.l
@@ -0,0 +1,374 @@
+%{
+/* scan.l: the (f)lex description file for the scanner. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991, 1992, 1993, 1994, 1997 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "bc.h"
+#include "global.h"
+#include "proto.h"
+#include <errno.h>
+
+/* Using flex, we can ask for a smaller input buffer.  With lex, this
+   does nothing! */
+
+#ifdef SMALL_BUF
+#undef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 512
+#endif
+
+/* Force . as last for now. */
+#define DOT_IS_LAST
+
+/* We want to define our own yywrap. */
+#undef yywrap
+_PROTOTYPE(int yywrap, (void));
+
+#if defined(LIBEDIT)
+/* Support for the BSD libedit with history for
+   nicer input on the interactive part of input. */
+
+#include <histedit.h>
+
+/* Have input call the following function. */
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+               bcel_input((char *)buf, &result, max_size)
+
+/* Variables to help interface editline with bc. */
+static const char *bcel_line = (char *)NULL;
+static int   bcel_len = 0;
+
+
+/* Required to get rid of that ugly ? default prompt! */
+char *
+null_prompt (EditLine *el)
+{
+  return "";
+}
+
+
+/* bcel_input puts upto MAX characters into BUF with the number put in
+   BUF placed in *RESULT.  If the yy input file is the same as
+   stdin, use editline.  Otherwise, just read it.
+*/
+
+static void
+bcel_input (buf, result, max)
+       char *buf;
+       int  *result;
+       int   max;
+{
+  if (!edit || yyin != stdin)
+    {
+      while ( (*result = read( fileno(yyin), buf, max )) < 0 )
+        if (errno != EINTR)
+         {
+           yyerror( "read() in flex scanner failed" );
+           exit (1);
+         }
+      return;
+    }
+
+  /* Do we need a new string? */
+  if (bcel_len == 0)
+    {
+      bcel_line = el_gets(edit, &bcel_len);
+      if (bcel_line == NULL) {
+       /* end of file */
+       *result = 0;
+       bcel_len = 0;
+       return;
+      }
+      if (bcel_len != 0)
+       history (hist, &histev, H_ENTER, bcel_line); 
+      fflush (stdout);
+    }
+
+  if (bcel_len <= max)
+    {
+      strncpy (buf, bcel_line, bcel_len);
+      *result = bcel_len;
+      bcel_len = 0;
+    }
+  else
+    {
+      strncpy (buf, bcel_line, max);
+      *result = max;
+      bcel_line += max;
+      bcel_len -= max;
+    }
+}
+#endif
+
+#ifdef READLINE
+/* Support for the readline and history libraries.  This allows
+   nicer input on the interactive part of input. */
+
+/* Have input call the following function. */
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+               rl_input((char *)buf, &result, max_size)
+
+/* Variables to help interface readline with bc. */
+static char *rl_line = (char *)NULL;
+static char *rl_start = (char *)NULL;
+static int   rl_len = 0;
+
+/* Definitions for readline access. */
+extern FILE *rl_instream;
+/* _PROTOTYPE(char *readline, (char *)); */
+
+/* rl_input puts upto MAX characters into BUF with the number put in
+   BUF placed in *RESULT.  If the yy input file is the same as
+   rl_instream (stdin), use readline.  Otherwise, just read it.
+*/
+
+static void
+rl_input (buf, result, max)
+       char *buf;
+       int  *result;
+       int   max;
+{
+  if (yyin != rl_instream)
+    {
+      while ( (*result = read( fileno(yyin), buf, max )) < 0 )
+        if (errno != EINTR)
+         {
+           yyerror( "read() in flex scanner failed" );
+           exit (1);
+         }
+      return;
+    }
+
+  /* Do we need a new string? */
+  if (rl_len == 0)
+    {
+      if (rl_start)
+       free(rl_start);
+      rl_start = readline ("");
+      if (rl_start == NULL) {
+       /* end of file */
+       *result = 0;
+       rl_len = 0;
+       return;
+      }
+      rl_line = rl_start;
+      rl_len = strlen (rl_line)+1;
+      if (rl_len != 1)
+       add_history (rl_line); 
+      rl_line[rl_len-1] = '\n';
+      fflush (stdout);
+    }
+
+  if (rl_len <= max)
+    {
+      strncpy (buf, rl_line, rl_len);
+      *result = rl_len;
+      rl_len = 0;
+    }
+  else
+    {
+      strncpy (buf, rl_line, max);
+      *result = max;
+      rl_line += max;
+      rl_len -= max;
+    }
+}
+#endif
+
+#if !defined(READLINE) && !defined(LIBEDIT)
+
+/* MINIX returns from read with < 0 if SIGINT is  encountered.
+   In flex, we can redefine YY_INPUT to the following.  In lex, this
+   does nothing! */
+#undef  YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
+           if (errno != EINTR) \
+               YY_FATAL_ERROR( "read() in flex scanner failed" );
+#endif
+
+%}
+DIGIT [0-9A-F]
+LETTER [a-z]
+%s slcomment
+%%
+"#"            {
+                 if (!std_only)
+                   BEGIN(slcomment);
+                 else
+                   yyerror ("illegal character: #");
+               }
+<slcomment>[^\n]* { BEGIN(INITIAL); }
+<slcomment>"\n" { line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
+define return(Define);
+break  return(Break);
+quit   return(Quit);
+length return(Length);
+return return(Return);
+for    return(For);
+if     return(If);
+while  return(While);
+sqrt   return(Sqrt);
+scale  return(Scale);
+ibase  return(Ibase);
+obase  return(Obase);
+auto   return(Auto);
+else   return(Else);
+read   return(Read);
+halt   return(Halt);
+last   return(Last);
+history {
+#if defined(READLINE) || defined(LIBEDIT)
+         return(HistoryVar);
+#else
+         yylval.s_value = strcopyof(yytext); return(NAME);
+#endif
+       }
+
+warranty return(Warranty);
+continue return(Continue);
+print  return(Print);
+limits return(Limits);
+"." {
+#ifdef DOT_IS_LAST
+       return(Last);
+#else
+       yyerror ("illegal character: %s",yytext);
+#endif
+    }
+"+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0]; 
+                                             return((int)yytext[0]); }
+&& { return(AND); }
+\|\| { return(OR); }
+"!" { return(NOT); }
+"*"|"/"|"%" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
+"="|\+=|-=|\*=|\/=|%=|\^=  { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
+=\+|=-|=\*|=\/|=%|=\^  { 
+#ifdef OLD_EQ_OP
+                        char warn_save;
+                        warn_save = warn_not_std;
+                        warn_not_std = TRUE;
+                        warn ("Old fashioned =<op>");
+                        warn_not_std = warn_save;
+                        yylval.c_value = yytext[1];
+#else
+                        yylval.c_value = '=';
+                        yyless (1);
+#endif
+                        return(ASSIGN_OP);
+                      }
+==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof(yytext); return(REL_OP); }
+\+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
+"\n" { line_no++; return(ENDOFLINE); }
+\\\n {  line_no++;  /* ignore a "quoted" newline */ }
+[ \t]+  { /* ignore spaces and tabs */ }
+"/*"  {
+       int c;
+
+       for (;;)
+         {
+           while ( ((c=input()) != '*') && (c != EOF)) 
+             /* eat it */
+             if (c == '\n') line_no++;
+           if (c == '*')
+             {
+               while ( (c=input()) == '*') /* eat it*/;
+               if (c == '/') break; /* at end of comment */
+               if (c == '\n') line_no++;
+             }
+           if (c == EOF)
+             {
+               fprintf (stderr,"EOF encountered in a comment.\n");
+               break;
+             }
+         }
+      }
+[a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
+\"[^\"]*\"  {
+             unsigned char *look;
+             int count = 0;
+             yylval.s_value = strcopyof(yytext);
+             for (look = yytext; *look != 0; look++)
+               {
+                 if (*look == '\n') line_no++;
+                 if (*look == '"')  count++;
+               }
+             if (count != 2) yyerror ("NUL character in string.");
+             return(STRING);
+           }
+{DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
+             unsigned char *src, *dst;
+             int len;
+             /* remove a trailing decimal point. */
+             len = strlen(yytext);
+             if (yytext[len-1] == '.')
+               yytext[len-1] = 0;
+             /* remove leading zeros. */
+             src = yytext;
+             dst = yytext;
+             while (*src == '0') src++;
+             if (*src == 0) src--;
+             /* Copy strings removing the newlines. */
+             while (*src != 0)
+               {
+                 if (*src == '\\')
+                   {
+                     src++; src++;
+                     line_no++;
+                   }
+                 else
+                   *dst++ = *src++;
+               }
+             *dst = 0;
+             yylval.s_value = strcopyof(yytext); 
+             return(NUMBER);
+           }
+.       {
+         if (yytext[0] < ' ')
+           yyerror ("illegal character: ^%c",yytext[0] + '@');
+         else
+           if (yytext[0] > '~')
+             yyerror ("illegal character: \\%03o", (int) yytext[0]);
+           else
+             yyerror ("illegal character: %s",yytext);
+       }
+%%
+
+
+
+/* This is the way to get multiple files input into lex. */
+
+int
+yywrap()
+{
+  if (!open_new_file ()) return (1);   /* EOF on standard in. */
+  return (0);                          /* We have more input. */
+}
diff --git a/bc/storage.c b/bc/storage.c
new file mode 100644 (file)
index 0000000..10ebf5c
--- /dev/null
@@ -0,0 +1,1067 @@
+/* storage.c:  Code and data storage manipulations.  This includes labels. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include "bcdefs.h"
+#include "global.h"
+#include "proto.h"
+
+
+/* Initialize the storage at the beginning of the run. */
+
+void
+init_storage ()
+{
+
+  /* Functions: we start with none and ask for more. */
+  f_count = 0;
+  more_functions ();
+  f_names[0] = "(main)";
+
+  /* Variables. */
+  v_count = 0;
+  more_variables ();
+  
+  /* Arrays. */
+  a_count = 0;
+  more_arrays ();
+
+  /* Other things... */
+  ex_stack = NULL;
+  fn_stack = NULL;
+  i_base = 10;
+  o_base = 10;
+  scale  = 0;
+#if defined(READLINE) || defined(LIBEDIT)
+  n_history = -1;      
+#endif
+  c_code = FALSE;
+  bc_init_numbers();
+}
+
+/* Three functions for increasing the number of functions, variables, or
+   arrays that are needed.  This adds another 32 of the requested object. */
+
+void
+more_functions (VOID)
+{
+  int old_count;
+  int indx;
+  bc_function *old_f;
+  bc_function *f;
+  char **old_names;
+
+  /* Save old information. */
+  old_count = f_count;
+  old_f = functions;
+  old_names = f_names;
+
+  /* Add a fixed amount and allocate new space. */
+  f_count += STORE_INCR;
+  functions = (bc_function *) bc_malloc (f_count*sizeof (bc_function));
+  f_names = (char **) bc_malloc (f_count*sizeof (char *));
+
+  /* Copy old ones. */
+  for (indx = 0; indx < old_count; indx++)
+    {
+      functions[indx] = old_f[indx];
+      f_names[indx] = old_names[indx];
+    }
+
+  /* Initialize the new ones. */
+  for (; indx < f_count; indx++)
+    {
+      f = &functions[indx];
+      f->f_defined = FALSE;
+      f->f_body = (char *) bc_malloc (BC_START_SIZE);
+      f->f_body_size = BC_START_SIZE;
+      f->f_code_size = 0;
+      f->f_label = NULL;
+      f->f_autos = NULL;
+      f->f_params = NULL;
+    }
+
+  /* Free the old elements. */
+  if (old_count != 0)
+    {
+      free (old_f);
+      free (old_names);
+    }
+}
+
+void
+more_variables ()
+{
+  int indx;
+  int old_count;
+  bc_var **old_var;
+  char **old_names;
+
+  /* Save the old values. */
+  old_count = v_count;
+  old_var = variables;
+  old_names = v_names;
+
+  /* Increment by a fixed amount and allocate. */
+  v_count += STORE_INCR;
+  variables = (bc_var **) bc_malloc (v_count*sizeof(bc_var *));
+  v_names = (char **) bc_malloc (v_count*sizeof(char *));
+
+  /* Copy the old variables. */
+  for (indx = 3; indx < old_count; indx++)
+    variables[indx] = old_var[indx];
+
+  /* Initialize the new elements. */
+  for (; indx < v_count; indx++)
+    variables[indx] = NULL;
+
+  /* Free the old elements. */
+  if (old_count != 0)
+    {
+      free (old_var);
+      free (old_names);
+    }
+}
+
+void
+more_arrays ()
+{
+  int indx;
+  int old_count;
+  bc_var_array **old_ary;
+  char **old_names;
+
+  /* Save the old values. */
+  old_count = a_count;
+  old_ary = arrays;
+  old_names = a_names;
+
+  /* Increment by a fixed amount and allocate. */
+  a_count += STORE_INCR;
+  arrays = (bc_var_array **) bc_malloc (a_count*sizeof(bc_var_array *));
+  a_names = (char **) bc_malloc (a_count*sizeof(char *));
+
+  /* Copy the old arrays. */
+  for (indx = 1; indx < old_count; indx++)
+    arrays[indx] = old_ary[indx];
+
+
+  /* Initialize the new elements. */
+  for (; indx < v_count; indx++)
+    arrays[indx] = NULL;
+
+  /* Free the old elements. */
+  if (old_count != 0)
+    {
+      free (old_ary);
+      free (old_names);
+    }
+}
+
+
+/* clear_func clears out function FUNC and makes it ready to redefine. */
+
+void
+clear_func (func)
+     int func;
+{
+  bc_function *f;
+  bc_label_group *lg;
+
+  /* Set the pointer to the function. */
+  f = &functions[func];
+  f->f_defined = FALSE;
+  /* XXX restore f_body to initial size??? */
+  f->f_code_size = 0;
+  if (f->f_autos != NULL)
+    {
+      free_args (f->f_autos);
+      f->f_autos = NULL;
+    }
+  if (f->f_params != NULL)
+    {
+      free_args (f->f_params);
+      f->f_params = NULL;
+    }
+  while (f->f_label != NULL)
+    {
+      lg = f->f_label->l_next;
+      free (f->f_label);
+      f->f_label = lg;
+    }
+}
+
+
+/*  Pop the function execution stack and return the top. */
+
+int
+fpop()
+{
+  fstack_rec *temp;
+  int retval;
+  
+  if (fn_stack != NULL)
+    {
+      temp = fn_stack;
+      fn_stack = temp->s_next;
+      retval = temp->s_val;
+      free (temp);
+    }
+  else
+    {
+      retval = 0;
+      rt_error ("function stack underflow, contact maintainer.");
+    }
+  return (retval);
+}
+
+
+/* Push VAL on to the function stack. */
+
+void
+fpush (val)
+     int val;
+{
+  fstack_rec *temp;
+  
+  temp = (fstack_rec *) bc_malloc (sizeof (fstack_rec));
+  temp->s_next = fn_stack;
+  temp->s_val = val;
+  fn_stack = temp;
+}
+
+
+/* Pop and discard the top element of the regular execution stack. */
+
+void
+pop ()
+{
+  estack_rec *temp;
+  
+  if (ex_stack != NULL)
+    {
+      temp = ex_stack;
+      ex_stack = temp->s_next;
+      bc_free_num (&temp->s_num);
+      free (temp);
+    }
+}
+
+
+/* Push a copy of NUM on to the regular execution stack. */
+
+void
+push_copy (num)
+     bc_num num;
+{
+  estack_rec *temp;
+
+  temp = (estack_rec *) bc_malloc (sizeof (estack_rec));
+  temp->s_num = bc_copy_num (num);
+  temp->s_next = ex_stack;
+  ex_stack = temp;
+}
+
+
+/* Push NUM on to the regular execution stack.  Do NOT push a copy. */
+
+void
+push_num (num)
+     bc_num num;
+{
+  estack_rec *temp;
+
+  temp = (estack_rec *) bc_malloc (sizeof (estack_rec));
+  temp->s_num = num;
+  temp->s_next = ex_stack;
+  ex_stack = temp;
+}
+
+
+/* Make sure the ex_stack has at least DEPTH elements on it.
+   Return TRUE if it has at least DEPTH elements, otherwise
+   return FALSE. */
+
+char
+check_stack (depth)
+     int depth;
+{
+  estack_rec *temp;
+
+  temp = ex_stack;
+  while ((temp != NULL) && (depth > 0))
+    {
+      temp = temp->s_next;
+      depth--;
+    }
+  if (depth > 0)
+    {
+      rt_error ("Stack error.");
+      return FALSE;
+    }
+  return TRUE;
+}
+
+
+/* The following routines manipulate simple variables and
+   array variables. */
+
+/* get_var returns a pointer to the variable VAR_NAME.  If one does not
+   exist, one is created. */
+
+bc_var *
+get_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  var_ptr = variables[var_name];
+  if (var_ptr == NULL)
+    {
+      var_ptr = variables[var_name] = (bc_var *) bc_malloc (sizeof (bc_var));
+      bc_init_num (&var_ptr->v_value);
+    }
+  return var_ptr;
+}
+
+
+/* get_array_num returns the address of the bc_num in the array
+   structure.  If more structure is requried to get to the index,
+   this routine does the work to create that structure. VAR_INDEX
+   is a zero based index into the arrays storage array. INDEX is
+   the index into the bc array. */
+
+bc_num *
+get_array_num (var_index, index)
+     int var_index;
+     long  index;
+{
+  bc_var_array *ary_ptr;
+  bc_array *a_var;
+  bc_array_node *temp;
+  int log, ix, ix1;
+  int sub [NODE_DEPTH];
+
+  /* Get the array entry. */
+  ary_ptr = arrays[var_index];
+  if (ary_ptr == NULL)
+    {
+      ary_ptr = arrays[var_index] =
+       (bc_var_array *) bc_malloc (sizeof (bc_var_array));
+      ary_ptr->a_value = NULL;
+      ary_ptr->a_next = NULL;
+      ary_ptr->a_param = FALSE;
+    }
+
+  a_var = ary_ptr->a_value;
+  if (a_var == NULL) {
+    a_var = ary_ptr->a_value = (bc_array *) bc_malloc (sizeof (bc_array));
+    a_var->a_tree = NULL;
+    a_var->a_depth = 0;
+  }
+
+  /* Get the index variable. */
+  sub[0] = index & NODE_MASK;
+  ix = index >> NODE_SHIFT;
+  log = 1;
+  while (ix > 0 || log < a_var->a_depth)
+    {
+      sub[log] = ix & NODE_MASK;
+      ix >>= NODE_SHIFT;
+      log++;
+    }
+  
+  /* Build any tree that is necessary. */
+  while (log > a_var->a_depth)
+    {
+      temp = (bc_array_node *) bc_malloc (sizeof(bc_array_node));
+      if (a_var->a_depth != 0)
+       {
+         temp->n_items.n_down[0] = a_var->a_tree;
+         for (ix=1; ix < NODE_SIZE; ix++)
+           temp->n_items.n_down[ix] = NULL;
+       }
+      else
+       {
+         for (ix=0; ix < NODE_SIZE; ix++)
+           temp->n_items.n_num[ix] = bc_copy_num(_zero_);
+       }
+      a_var->a_tree = temp;
+      a_var->a_depth++;
+    }
+  
+  /* Find the indexed variable. */
+  temp = a_var->a_tree;
+  while ( log-- > 1)
+    {
+      ix1 = sub[log];
+      if (temp->n_items.n_down[ix1] == NULL)
+       {
+         temp->n_items.n_down[ix1] =
+           (bc_array_node *) bc_malloc (sizeof(bc_array_node));
+         temp = temp->n_items.n_down[ix1];
+         if (log > 1)
+           for (ix=0; ix < NODE_SIZE; ix++)
+             temp->n_items.n_down[ix] = NULL;
+         else
+           for (ix=0; ix < NODE_SIZE; ix++)
+             temp->n_items.n_num[ix] = bc_copy_num(_zero_);
+       }
+      else
+       temp = temp->n_items.n_down[ix1];
+    }
+  
+  /* Return the address of the indexed variable. */
+  return &(temp->n_items.n_num[sub[0]]);
+}
+
+
+/* Store the top of the execution stack into VAR_NAME.  
+   This includes the special variables ibase, obase, and scale. */
+
+void
+store_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+  long temp;
+  char toobig;
+
+  if (var_name > 3)
+    {
+      /* It is a simple variable. */
+      var_ptr = get_var (var_name);
+      if (var_ptr != NULL)
+       {
+         bc_free_num(&var_ptr->v_value);
+         var_ptr->v_value = bc_copy_num (ex_stack->s_num);
+       }
+    }
+  else
+    {
+      /* It is a special variable... */
+      toobig = FALSE;
+      temp = 0;
+      if (bc_is_neg (ex_stack->s_num))
+       {
+         switch (var_name)
+           {
+           case 0:
+             rt_warn ("negative ibase, set to 2");
+             temp = 2;
+             break;
+           case 1:
+             rt_warn ("negative obase, set to 2");
+             temp = 2;
+             break;
+           case 2:
+             rt_warn ("negative scale, set to 0");
+             temp = 0;
+             break;
+#if defined(READLINE) || defined(LIBEDIT)
+           case 3:
+             temp = -1;
+             break;
+#endif
+           }
+       }
+      else
+       {
+         temp = bc_num2long (ex_stack->s_num);
+         if (!bc_is_zero (ex_stack->s_num) && temp == 0)
+           toobig = TRUE;
+       }
+      switch (var_name)
+       {
+       case 0:
+         if (temp < 2 && !toobig)
+           {
+             i_base = 2;
+             rt_warn ("ibase too small, set to 2");
+           }
+         else
+           if (temp > 16 || toobig)
+             {
+               i_base = 16;
+               rt_warn ("ibase too large, set to 16");
+             }
+           else
+             i_base = (int) temp;
+         break;
+
+       case 1:
+         if (temp < 2 && !toobig)
+           {
+             o_base = 2;
+             rt_warn ("obase too small, set to 2");
+           }
+         else
+           if (temp > BC_BASE_MAX || toobig)
+             {
+               o_base = BC_BASE_MAX;
+               rt_warn ("obase too large, set to %d", BC_BASE_MAX);
+             }
+           else
+             o_base = (int) temp;
+         break;
+
+       case 2:
+         /*  WARNING:  The following if statement may generate a compiler
+             warning if INT_MAX == LONG_MAX.  This is NOT a problem. */
+         if (temp > BC_SCALE_MAX || toobig )
+           {
+             scale = BC_SCALE_MAX;
+             rt_warn ("scale too large, set to %d", BC_SCALE_MAX);
+           }
+         else
+           scale = (int) temp;
+         break;
+
+#if defined(READLINE) || defined(LIBEDIT)
+       case 3:
+         if (toobig)
+           {
+             temp = -1;
+             rt_warn ("history too large, set to unlimited");
+             UNLIMIT_HISTORY;
+           }
+         else
+           {
+             n_history = temp;
+             if (temp < 0)
+               UNLIMIT_HISTORY;
+             else
+               HISTORY_SIZE(n_history);
+           }
+#endif
+       }
+    }
+}
+
+
+/* Store the top of the execution stack into array VAR_NAME. 
+   VAR_NAME is the name of an array, and the next to the top
+   of stack for the index into the array. */
+
+void
+store_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long index;
+
+  if (!check_stack(2)) return;
+  index = bc_num2long (ex_stack->s_next->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+      (index == 0 && !bc_is_zero(ex_stack->s_next->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+       {
+         bc_free_num (num_ptr);
+         *num_ptr = bc_copy_num (ex_stack->s_num);
+         bc_free_num (&ex_stack->s_next->s_num);
+         ex_stack->s_next->s_num = ex_stack->s_num;
+         bc_init_num (&ex_stack->s_num);
+         pop();
+       }
+    }
+}
+
+
+/*  Load a copy of VAR_NAME on to the execution stack.  This includes
+    the special variables ibase, obase and scale.  */
+
+void
+load_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  switch (var_name)
+    {
+
+    case 0:
+      /* Special variable ibase. */
+      push_copy (_zero_);
+      bc_int2num (&ex_stack->s_num, i_base);
+      break;
+
+    case 1:
+      /* Special variable obase. */
+      push_copy (_zero_);
+      bc_int2num (&ex_stack->s_num, o_base);
+      break;
+
+    case 2:
+      /* Special variable scale. */
+      push_copy (_zero_);
+      bc_int2num (&ex_stack->s_num, scale);
+      break;
+
+#if defined(READLINE) || defined(LIBEDIT)
+    case 3:
+      /* Special variable history. */
+      push_copy (_zero_);
+      bc_int2num (&ex_stack->s_num, n_history);
+      break;
+#endif
+
+    default:
+      /* It is a simple variable. */
+      var_ptr = variables[var_name];
+      if (var_ptr != NULL)
+       push_copy (var_ptr->v_value);
+      else
+       push_copy (_zero_);
+    }
+}
+
+
+/*  Load a copy of VAR_NAME on to the execution stack.  This includes
+    the special variables ibase, obase and scale.  */
+
+void
+load_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long   index;
+
+  if (!check_stack(1)) return;
+  index = bc_num2long (ex_stack->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+     (index == 0 && !bc_is_zero(ex_stack->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+       {
+         pop();
+         push_copy (*num_ptr);
+       }
+    }
+}
+
+
+/* Decrement VAR_NAME by one.  This includes the special variables
+   ibase, obase, and scale. */
+
+void
+decr_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  switch (var_name)
+    {
+
+    case 0: /* ibase */
+      if (i_base > 2)
+       i_base--;
+      else
+       rt_warn ("ibase too small in --");
+      break;
+      
+    case 1: /* obase */
+      if (o_base > 2)
+       o_base--;
+      else
+       rt_warn ("obase too small in --");
+      break;
+
+    case 2: /* scale */
+      if (scale > 0)
+       scale--;
+      else
+       rt_warn ("scale can not be negative in -- ");
+      break;
+
+#if defined(READLINE) || defined(LIBEDIT)
+    case 3: /* history */
+      n_history--;
+      if (n_history >= 0)
+       HISTORY_SIZE(n_history);
+      else
+       {
+         n_history = -1;
+         rt_warn ("history is negative, set to unlimited");
+         UNLIMIT_HISTORY;
+       }
+#endif
+
+    default: /* It is a simple variable. */
+      var_ptr = get_var (var_name);
+      if (var_ptr != NULL)
+       bc_sub (var_ptr->v_value,_one_,&var_ptr->v_value, 0);
+    }
+}
+
+
+/* Decrement VAR_NAME by one.  VAR_NAME is an array, and the top of
+   the execution stack is the index and it is popped off the stack. */
+
+void
+decr_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long   index;
+
+  /* It is an array variable. */
+  if (!check_stack (1)) return;
+  index = bc_num2long (ex_stack->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+     (index == 0 && !bc_is_zero (ex_stack->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+       {
+         pop ();
+         bc_sub (*num_ptr, _one_, num_ptr, 0);
+       }
+    }
+}
+
+
+/* Increment VAR_NAME by one.  This includes the special variables
+   ibase, obase, and scale. */
+
+void
+incr_var (var_name)
+     int var_name;
+{
+  bc_var *var_ptr;
+
+  switch (var_name)
+    {
+
+    case 0: /* ibase */
+      if (i_base < 16)
+       i_base++;
+      else
+       rt_warn ("ibase too big in ++");
+      break;
+
+    case 1: /* obase */
+      if (o_base < BC_BASE_MAX)
+       o_base++;
+      else
+       rt_warn ("obase too big in ++");
+      break;
+
+    case 2:
+      if (scale < BC_SCALE_MAX)
+       scale++;
+      else
+       rt_warn ("Scale too big in ++");
+      break;
+
+#if defined(READLINE) || defined(LIBEDIT)
+    case 3: /* history */
+      n_history++;
+      if (n_history > 0)
+       HISTORY_SIZE(n_history);
+      else
+       {
+         n_history = -1;
+         rt_warn ("history set to unlimited");
+         UNLIMIT_HISTORY;
+       }
+#endif
+
+    default:  /* It is a simple variable. */
+      var_ptr = get_var (var_name);
+      if (var_ptr != NULL)
+       bc_add (var_ptr->v_value, _one_, &var_ptr->v_value, 0);
+
+    }
+}
+
+
+/* Increment VAR_NAME by one.  VAR_NAME is an array and top of
+   execution stack is the index and is popped off the stack. */
+
+void
+incr_array (var_name)
+     int var_name;
+{
+  bc_num *num_ptr;
+  long   index;
+
+  if (!check_stack (1)) return;
+  index = bc_num2long (ex_stack->s_num);
+  if (index < 0 || index > BC_DIM_MAX ||
+      (index == 0 && !bc_is_zero (ex_stack->s_num))) 
+    rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
+  else
+    {
+      num_ptr = get_array_num (var_name, index);
+      if (num_ptr != NULL)
+       {
+         pop ();
+         bc_add (*num_ptr, _one_, num_ptr, 0);
+       }
+    }
+}
+
+
+/* Routines for processing autos variables and parameters. */
+
+/* NAME is an auto variable that needs to be pushed on its stack. */
+
+void
+auto_var (name)
+     int name;
+{
+  bc_var *v_temp;
+  bc_var_array *a_temp;
+  int ix;
+
+  if (name > 0)
+    {
+      /* A simple variable. */
+      ix = name;
+      v_temp = (bc_var *) bc_malloc (sizeof (bc_var));
+      v_temp->v_next = variables[ix];
+      bc_init_num (&v_temp->v_value);
+      variables[ix] = v_temp;
+    }
+  else
+    {
+      /* An array variable. */
+      ix = -name;
+      a_temp = (bc_var_array *) bc_malloc (sizeof (bc_var_array));
+      a_temp->a_next = arrays[ix];
+      a_temp->a_value = NULL;
+      a_temp->a_param = FALSE;
+      arrays[ix] = a_temp;
+    } 
+}
+
+
+/* Free_a_tree frees everything associated with an array variable tree.
+   This is used when popping an array variable off its auto stack.  */
+
+void
+free_a_tree ( root, depth )
+     bc_array_node *root;
+     int depth;
+{
+  int ix;
+
+  if (root != NULL)
+    {
+      if (depth > 1)
+       for (ix = 0; ix < NODE_SIZE; ix++)
+         free_a_tree (root->n_items.n_down[ix], depth-1);
+      else
+       for (ix = 0; ix < NODE_SIZE; ix++)
+         bc_free_num ( &(root->n_items.n_num[ix]));
+      free (root);
+    }
+}
+
+
+/* LIST is an NULL terminated list of varible names that need to be
+   popped off their auto stacks. */
+
+void
+pop_vars (list)
+     arg_list *list;
+{
+  bc_var *v_temp;
+  bc_var_array *a_temp;
+  int    ix;
+
+  while (list != NULL)
+    {
+      ix = list->av_name;
+      if (ix > 0)
+       {
+         /* A simple variable. */
+         v_temp = variables[ix];
+         if (v_temp != NULL)
+           {
+             variables[ix] = v_temp->v_next;
+             bc_free_num (&v_temp->v_value);
+             free (v_temp);
+           }
+       }
+      else
+       {
+         /* An array variable. */
+         ix = -ix;
+         a_temp = arrays[ix];
+         if (a_temp != NULL)
+           {
+             arrays[ix] = a_temp->a_next;
+             if (!a_temp->a_param && a_temp->a_value != NULL)
+               {
+                 free_a_tree (a_temp->a_value->a_tree,
+                              a_temp->a_value->a_depth);
+                 free (a_temp->a_value);
+               }
+             free (a_temp);
+           }
+       } 
+      list = list->next;
+    }
+}
+
+/* COPY_NODE: Copies an array node for a call by value parameter. */
+bc_array_node *
+copy_tree (ary_node, depth)
+     bc_array_node *ary_node;
+     int depth;
+{
+  bc_array_node *res = (bc_array_node *) bc_malloc (sizeof(bc_array_node));
+  int i;
+
+  if (depth > 1)
+    for (i=0; i<NODE_SIZE; i++)
+      if (ary_node->n_items.n_down[i] != NULL)
+       res->n_items.n_down[i] =
+         copy_tree (ary_node->n_items.n_down[i], depth - 1);
+      else
+       res->n_items.n_down[i] = NULL;
+  else
+    for (i=0; i<NODE_SIZE; i++)
+      if (ary_node->n_items.n_num[i] != NULL)
+       res->n_items.n_num[i] = bc_copy_num (ary_node->n_items.n_num[i]);
+      else
+       res->n_items.n_num[i] = NULL;
+  return res;
+}
+
+/* COPY_ARRAY: Copies an array for a call by value array parameter. 
+   ARY is the pointer to the bc_array structure. */
+
+bc_array *
+copy_array (ary)
+     bc_array *ary;
+{
+  bc_array *res = (bc_array *) bc_malloc (sizeof(bc_array));
+  res->a_depth = ary->a_depth;
+  res->a_tree = copy_tree (ary->a_tree, ary->a_depth);
+  return (res);
+}
+
+
+/* A call is being made to FUNC.  The call types are at PC.  Process
+   the parameters by doing an auto on the parameter variable and then
+   store the value at the new variable or put a pointer the the array
+   variable. */
+
+void
+process_params (pc, func)
+     program_counter *pc;
+     int func;
+{
+  char ch;
+  arg_list *params;
+  int ix, ix1;
+  bc_var *v_temp;
+  bc_var_array *a_src, *a_dest;
+  bc_num *n_temp;
+  
+  /* Get the parameter names from the function. */
+  params = functions[func].f_params;
+
+  while ((ch = byte(pc)) != ':')
+    {
+      if (params != NULL)
+       {
+         if ((ch == '0') && params->av_name > 0)
+           {
+             /* A simple variable. */
+             ix = params->av_name;
+             v_temp = (bc_var *) bc_malloc (sizeof(bc_var));
+             v_temp->v_next = variables[ix];
+             v_temp->v_value = ex_stack->s_num;
+             bc_init_num (&ex_stack->s_num);
+             variables[ix] = v_temp;
+           }
+         else
+           if ((ch == '1') && (params->av_name < 0))
+             {
+               /* The variables is an array variable. */
+       
+               /* Compute source index and make sure some structure exists. */
+               ix = (int) bc_num2long (ex_stack->s_num);
+               n_temp = get_array_num (ix, 0);    
+       
+               /* Push a new array and Compute Destination index */
+               auto_var (params->av_name);  
+               ix1 = -params->av_name;
+
+               /* Set up the correct pointers in the structure. */
+               if (ix == ix1) 
+                 a_src = arrays[ix]->a_next;
+               else
+                 a_src = arrays[ix];
+               a_dest = arrays[ix1];
+               if (params->arg_is_var)
+                 {
+                   a_dest->a_param = TRUE;
+                   a_dest->a_value = a_src->a_value;
+                 }
+               else
+                 {
+                   a_dest->a_param = FALSE;
+                   a_dest->a_value = copy_array (a_src->a_value);
+                 }
+             }
+           else
+             {
+               if (params->av_name < 0)
+                 rt_error ("Parameter type mismatch parameter %s.",
+                           a_names[-params->av_name]);
+               else
+                 rt_error ("Parameter type mismatch, parameter %s.",
+                           v_names[params->av_name]);
+               params++;
+             }
+         pop ();
+       }
+      else
+       {
+           rt_error ("Parameter number mismatch");
+           return;
+       }
+      params = params->next;
+    }
+  if (params != NULL) 
+    rt_error ("Parameter number mismatch");
+}
diff --git a/bc/util.c b/bc/util.c
new file mode 100644 (file)
index 0000000..48bcbe0
--- /dev/null
+++ b/bc/util.c
@@ -0,0 +1,873 @@
+/* util.c: Utility routines for bc. */
+
+/*  This file is part of GNU bc.
+    Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111 USA
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+
+#include "bcdefs.h"
+#ifndef VARARGS
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "global.h"
+#include "proto.h"
+
+
+/* strcopyof mallocs new memory and copies a string to to the new
+   memory. */
+
+char *
+strcopyof (str)
+     char *str;
+{
+  char *temp;
+
+  temp = (char *) bc_malloc (strlen (str)+1);
+  return (strcpy (temp,str));
+}
+
+
+/* nextarg adds another value to the list of arguments. */
+
+arg_list *
+nextarg (args, val, is_var)
+     arg_list *args;
+     int val;
+     int is_var;
+{ arg_list *temp;
+
+  temp = (arg_list *) bc_malloc (sizeof (arg_list));
+  temp->av_name = val;
+  temp->arg_is_var = is_var;
+  temp->next = args;
+  return (temp);
+}
+
+
+/* For generate, we must produce a string in the form
+    "val,val,...,val".  We also need a couple of static variables
+   for retaining old generated strings.  It also uses a recursive
+   function that builds the string. */
+
+static char *arglist1 = NULL, *arglist2 = NULL;
+
+
+/* make_arg_str does the actual construction of the argument string.
+   ARGS is the pointer to the list and LEN is the maximum number of
+   characters needed.  1 char is the minimum needed. 
+ */
+
+_PROTOTYPE (static char *make_arg_str, (arg_list *args, int len));
+
+static char *
+make_arg_str (args, len)
+      arg_list *args;
+      int len;
+{
+  char *temp;
+  char sval[20];
+
+  /* Recursive call. */
+  if (args != NULL)
+    temp = make_arg_str (args->next, len+12);
+  else
+    {
+      temp = (char *) bc_malloc (len);
+      *temp = 0;
+      return temp;
+    }
+
+  /* Add the current number to the end of the string. */
+  if (args->arg_is_var)
+    if (len != 1) 
+      sprintf (sval, "*%d,", args->av_name);
+    else
+      sprintf (sval, "*%d", args->av_name);
+  else
+    if (len != 1) 
+      sprintf (sval, "%d,", args->av_name);
+    else
+      sprintf (sval, "%d", args->av_name);
+  temp = strcat (temp, sval);
+  return (temp);
+}
+
+char *
+arg_str (args)
+     arg_list *args;
+{
+  if (arglist2 != NULL) 
+    free (arglist2);
+  arglist2 = arglist1;
+  arglist1 = make_arg_str (args, 1);
+  return (arglist1);
+}
+
+char *
+call_str (args)
+     arg_list *args;
+{
+  arg_list *temp;
+  int       arg_count;
+  int       ix;
+  
+  if (arglist2 != NULL) 
+    free (arglist2);
+  arglist2 = arglist1;
+
+  /* Count the number of args and add the 0's and 1's. */
+  for (temp = args, arg_count = 0; temp != NULL; temp = temp->next)
+    arg_count++;
+  arglist1 = (char *) bc_malloc(arg_count+1);
+  for (temp = args, ix=0; temp != NULL; temp = temp->next)
+    arglist1[ix++] = ( temp->av_name ? '1' : '0');
+  arglist1[ix] = 0;
+      
+  return (arglist1);
+}
+
+/* free_args frees an argument list ARGS. */
+
+void
+free_args (args)
+      arg_list *args;
+{ 
+  arg_list *temp;
+  temp = args;
+  while (temp != NULL)
+    {
+      args = args->next;
+      free (temp);
+      temp = args;
+    }
+}
+
+
+/* Check for valid parameter (PARAMS) and auto (AUTOS) lists.
+   There must be no duplicates any where.  Also, this is where
+   warnings are generated for array parameters. */
+
+void
+check_params ( params, autos )
+     arg_list *params, *autos;
+{
+  arg_list *tmp1, *tmp2;
+
+  /* Check for duplicate parameters. */
+  if (params != NULL)
+    {
+      tmp1 = params;
+      while (tmp1 != NULL)
+       {
+         tmp2 = tmp1->next;
+         while (tmp2 != NULL)
+           {
+             if (tmp2->av_name == tmp1->av_name) 
+               yyerror ("duplicate parameter names");
+             tmp2 = tmp2->next;
+           }
+         if (tmp1->arg_is_var)
+           warn ("Variable array parameter");
+         tmp1 = tmp1->next;
+       }
+    }
+
+  /* Check for duplicate autos. */
+  if (autos != NULL)
+    {
+      tmp1 = autos;
+      while (tmp1 != NULL)
+       {
+         tmp2 = tmp1->next;
+         while (tmp2 != NULL)
+           {
+             if (tmp2->av_name == tmp1->av_name) 
+               yyerror ("duplicate auto variable names");
+             tmp2 = tmp2->next;
+           }
+         if (tmp1->arg_is_var)
+           yyerror ("* not allowed here");
+         tmp1 = tmp1->next;
+       }
+    }
+
+  /* Check for duplicate between parameters and autos. */
+  if ((params != NULL) && (autos != NULL))
+    {
+      tmp1 = params;
+      while (tmp1 != NULL)
+       {
+         tmp2 = autos;
+         while (tmp2 != NULL)
+           {
+             if (tmp2->av_name == tmp1->av_name) 
+               yyerror ("variable in both parameter and auto lists");
+             tmp2 = tmp2->next;
+           }
+         tmp1 = tmp1->next;
+       }
+    }
+}
+
+
+/* Initialize the code generator the parser. */
+
+void
+init_gen ()
+{
+  /* Get things ready. */
+  break_label = 0;
+  continue_label = 0;
+  next_label  = 1;
+  out_count = 2;
+  if (compile_only) 
+    printf ("@i");
+  else
+    init_load ();
+  had_error = FALSE;
+  did_gen = FALSE;
+}
+
+
+/* generate code STR for the machine. */
+
+void
+generate (str)
+      char *str;
+{
+  did_gen = TRUE;
+  if (compile_only)
+    {
+      printf ("%s",str);
+      out_count += strlen(str);
+      if (out_count > 60)
+       {
+         printf ("\n");
+         out_count = 0;
+       }
+    }
+  else
+    load_code (str);
+}
+
+
+/* Execute the current code as loaded. */
+
+void
+run_code()
+{
+  /* If no compile errors run the current code. */
+  if (!had_error && did_gen)
+    {
+      if (compile_only)
+       {
+         printf ("@r\n"); 
+         out_count = 0;
+       }
+      else
+       execute ();
+    }
+
+  /* Reinitialize the code generation and machine. */
+  if (did_gen)
+    init_gen();
+  else
+    had_error = FALSE;
+}
+
+
+/* Output routines: Write a character CH to the standard output.
+   It keeps track of the number of characters output and may
+   break the output with a "\<cr>".  Always used for numbers. */
+
+void
+out_char (ch)
+     int ch;
+{
+  if (ch == '\n')
+    {
+      out_col = 0;
+      putchar ('\n');
+    }
+  else
+    {
+      out_col++;
+      if (out_col == line_size-1)
+       {
+         putchar ('\\');
+         putchar ('\n');
+         out_col = 1;
+       }
+      putchar (ch);
+    }
+}
+
+/* Output routines: Write a character CH to the standard output.
+   It keeps track of the number of characters output and may
+   break the output with a "\<cr>".  This one is for strings.
+   In POSIX bc, strings are not broken across lines. */
+
+void
+out_schar (ch)
+     int ch;
+{
+  if (ch == '\n')
+    {
+      out_col = 0;
+      putchar ('\n');
+    }
+  else
+    {
+      if (!std_only)
+       {
+         out_col++;
+         if (out_col == line_size-1)
+           {
+             putchar ('\\');
+             putchar ('\n');
+             out_col = 1;
+           }
+       }
+      putchar (ch);
+    }
+}
+
+
+/* The following are "Symbol Table" routines for the parser. */
+
+/*  find_id returns a pointer to node in TREE that has the correct
+    ID.  If there is no node in TREE with ID, NULL is returned. */
+
+id_rec *
+find_id (tree, id)
+     id_rec *tree;
+     char   *id;
+{
+  int cmp_result;
+  
+  /* Check for an empty tree. */
+  if (tree == NULL)
+    return NULL;
+
+  /* Recursively search the tree. */
+  cmp_result = strcmp (id, tree->id);
+  if (cmp_result == 0)
+    return tree;  /* This is the item. */
+  else if (cmp_result < 0)
+    return find_id (tree->left, id);
+  else
+    return find_id (tree->right, id);  
+}
+
+
+/* insert_id_rec inserts a NEW_ID rec into the tree whose ROOT is
+   provided.  insert_id_rec returns TRUE if the tree height from
+   ROOT down is increased otherwise it returns FALSE.  This is a
+   recursive balanced binary tree insertion algorithm. */
+
+int insert_id_rec (root, new_id)
+     id_rec **root;
+     id_rec *new_id;
+{
+  id_rec *A, *B;
+
+  /* If root is NULL, this where it is to be inserted. */
+  if (*root == NULL)
+    {
+      *root = new_id;
+      new_id->left = NULL;
+      new_id->right = NULL;
+      new_id->balance = 0;
+      return (TRUE);
+    }
+
+  /* We need to search for a leaf. */
+  if (strcmp (new_id->id, (*root)->id) < 0)
+    {
+      /* Insert it on the left. */
+      if (insert_id_rec (&((*root)->left), new_id))
+       {
+         /* The height increased. */
+         (*root)->balance --;
+         
+      switch ((*root)->balance)
+       {
+       case  0:  /* no height increase. */
+         return (FALSE);
+       case -1:  /* height increase. */
+         return (TRUE);
+       case -2:  /* we need to do a rebalancing act. */
+         A = *root;
+         B = (*root)->left;
+         if (B->balance <= 0)
+           {
+             /* Single Rotate. */
+             A->left = B->right;
+             B->right = A;
+             *root = B;
+             A->balance = 0;
+             B->balance = 0;
+           }
+         else
+           {
+             /* Double Rotate. */
+             *root = B->right;
+             B->right = (*root)->left;
+             A->left = (*root)->right;
+             (*root)->left = B;
+             (*root)->right = A;
+             switch ((*root)->balance)
+               {
+               case -1:
+                 A->balance = 1;
+                 B->balance = 0;
+                 break;
+               case  0:
+                 A->balance = 0;
+                 B->balance = 0;
+                 break;
+               case  1:
+                 A->balance = 0;
+                 B->balance = -1;
+                 break;
+               }
+             (*root)->balance = 0;
+           }
+       }     
+       } 
+    }
+  else
+    {
+      /* Insert it on the right. */
+      if (insert_id_rec (&((*root)->right), new_id))
+       {
+         /* The height increased. */
+         (*root)->balance ++;
+         switch ((*root)->balance)
+           {
+           case 0:  /* no height increase. */
+             return (FALSE);
+           case 1:  /* height increase. */
+             return (TRUE);
+           case 2:  /* we need to do a rebalancing act. */
+             A = *root;
+             B = (*root)->right;
+             if (B->balance >= 0)
+               {
+                 /* Single Rotate. */
+                 A->right = B->left;
+                 B->left = A;
+                 *root = B;
+                 A->balance = 0;
+                 B->balance = 0;
+               }
+             else
+               {
+                 /* Double Rotate. */
+                 *root = B->left;
+                 B->left = (*root)->right;
+                 A->right = (*root)->left;
+                 (*root)->left = A;
+                 (*root)->right = B;
+                 switch ((*root)->balance)
+                   {
+                   case -1:
+                     A->balance = 0;
+                     B->balance = 1;
+                     break;
+                   case  0:
+                     A->balance = 0;
+                     B->balance = 0;
+                     break;
+                   case  1:
+                     A->balance = -1;
+                     B->balance = 0;
+                     break;
+                   }
+                 (*root)->balance = 0;
+               }
+           }     
+       } 
+    }
+  
+  /* If we fall through to here, the tree did not grow in height. */
+  return (FALSE);
+}
+
+
+/* Initialize variables for the symbol table tree. */
+
+void
+init_tree()
+{
+  name_tree  = NULL;
+  next_array = 1;
+  next_func  = 1;
+  /* 0 => ibase, 1 => obase, 2 => scale, 3 => history, 4 => last. */
+  next_var   = 5;
+}
+
+
+/* Lookup routines for symbol table names. */
+
+int
+lookup (name, namekind)
+     char *name;
+     int  namekind;
+{
+  id_rec *id;
+
+  /* Warn about non-standard name. */
+  if (strlen(name) != 1)
+    warn ("multiple letter name - %s", name);
+
+  /* Look for the id. */
+  id = find_id (name_tree, name);
+  if (id == NULL)
+    {
+      /* We need to make a new item. */
+      id = (id_rec *) bc_malloc (sizeof (id_rec));
+      id->id = strcopyof (name);
+      id->a_name = 0;
+      id->f_name = 0;
+      id->v_name = 0;
+      insert_id_rec (&name_tree, id);
+    }
+
+  /* Return the correct value. */
+  switch (namekind)
+    {
+      
+    case ARRAY:
+      /* ARRAY variable numbers are returned as negative numbers. */
+      if (id->a_name != 0)
+       {
+         free (name);
+         return (-id->a_name);
+       }
+      id->a_name = next_array++;
+      a_names[id->a_name] = name;
+      if (id->a_name < MAX_STORE)
+       {
+         if (id->a_name >= a_count)
+           more_arrays ();
+         return (-id->a_name);
+       }
+      yyerror ("Too many array variables");
+      exit (1);
+
+    case FUNCT:
+    case FUNCTDEF:
+      if (id->f_name != 0)
+       {
+         free(name);
+         /* Check to see if we are redefining a math lib function. */ 
+         if (use_math && namekind == FUNCTDEF && id->f_name <= 6)
+           id->f_name = next_func++;
+         return (id->f_name);
+       }
+      id->f_name = next_func++;
+      f_names[id->f_name] = name;
+      if (id->f_name < MAX_STORE)
+       {
+         if (id->f_name >= f_count)
+           more_functions ();
+         return (id->f_name);
+       }
+      yyerror ("Too many functions");
+      exit (1);
+
+    case SIMPLE:
+      if (id->v_name != 0)
+       {
+         free(name);
+         return (id->v_name);
+       }
+      id->v_name = next_var++;
+      v_names[id->v_name - 1] = name;
+      if (id->v_name <= MAX_STORE)
+       {
+         if (id->v_name >= v_count)
+           more_variables ();
+         return (id->v_name);
+       }
+      yyerror ("Too many variables");
+      exit (1);
+    }
+
+  yyerror ("End of util.c/lookup() reached.  Please report this bug.");
+  exit (1);
+  /* not reached */
+}
+
+
+/* Print the welcome banner. */
+
+void 
+welcome()
+{
+  printf ("This is free software with ABSOLUTELY NO WARRANTY.\n");
+  printf ("For details type `warranty'. \n");
+}
+
+/* Print out the version information. */
+void
+show_bc_version()
+{
+  printf("%s %s\n%s\n", PACKAGE, VERSION, BC_COPYRIGHT);
+}
+
+
+/* Print out the warranty information. */
+
+void 
+warranty(prefix)
+     char *prefix;
+{
+  printf ("\n%s", prefix);
+  show_bc_version ();
+  printf ("\n"
+"    This program is free software; you can redistribute it and/or modify\n"
+"    it under the terms of the GNU General Public License as published by\n"
+"    the Free Software Foundation; either version 2 of the License , or\n"
+"    (at your option) any later version.\n\n"
+"    This program is distributed in the hope that it will be useful,\n"
+"    but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+"    GNU General Public License for more details.\n\n"
+"    You should have received a copy of the GNU General Public License\n"
+"    along with this program. If not, write to\n\n"
+"       The Free Software Foundation, Inc.\n"
+"       59 Temple Place, Suite 330\n"
+"       Boston, MA 02111, USA.\n\n");
+}
+
+/* Print out the limits of this program. */
+
+void
+limits()
+{
+  printf ("BC_BASE_MAX     = %d\n",  BC_BASE_MAX);
+  printf ("BC_DIM_MAX      = %ld\n", (long) BC_DIM_MAX);
+  printf ("BC_SCALE_MAX    = %d\n",  BC_SCALE_MAX);
+  printf ("BC_STRING_MAX   = %d\n",  BC_STRING_MAX);
+  printf ("MAX Exponent    = %ld\n", (long) LONG_MAX);
+  printf ("Number of vars  = %ld\n", (long) MAX_STORE);
+#ifdef OLD_EQ_OP
+  printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
+#endif 
+}
+
+/* bc_malloc will check the return value so all other places do not
+   have to do it!  SIZE is the number of bytes to allocate. */
+
+char *
+bc_malloc (size)
+     int size;
+{
+  char *ptr;
+
+  ptr = (char *) malloc (size);
+  if (ptr == NULL)
+    out_of_memory ();
+
+  return ptr;
+}
+
+
+/* The following routines are error routines for various problems. */
+
+/* Malloc could not get enought memory. */
+
+void
+out_of_memory()
+{
+  fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
+  exit (1);
+}
+
+
+
+/* The standard yyerror routine.  Built with variable number of argumnets. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+yyerror (char *str, ...)
+#else
+void
+yyerror (str)
+     char *str;
+#endif
+#else
+void
+yyerror (str, va_alist)
+     char *str;
+#endif
+{
+  char *name;
+  va_list args;
+
+#ifndef VARARGS   
+   va_start (args, str);
+#else
+   va_start (args);
+#endif
+  if (is_std_in)
+    name = "(standard_in)";
+  else
+    name = file_name;
+  fprintf (stderr,"%s %d: ",name,line_no);
+  vfprintf (stderr, str, args);
+  fprintf (stderr, "\n");
+  had_error = TRUE;
+  va_end (args);
+}
+
+
+/* The routine to produce warnings about non-standard features
+   found during parsing. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void 
+warn (char *mesg, ...)
+#else
+void
+warn (mesg)
+     char *mesg;
+#endif
+#else
+void
+warn (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  char *name;
+  va_list args;
+
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  if (std_only)
+    {
+      if (is_std_in)
+       name = "(standard_in)";
+      else
+       name = file_name;
+      fprintf (stderr,"%s %d: ",name,line_no);
+      vfprintf (stderr, mesg, args);
+      fprintf (stderr, "\n");
+      had_error = TRUE;
+    }
+  else
+    if (warn_not_std)
+      {
+       if (is_std_in)
+         name = "(standard_in)";
+       else
+         name = file_name;
+       fprintf (stderr,"%s %d: (Warning) ",name,line_no);
+       vfprintf (stderr, mesg, args);
+       fprintf (stderr, "\n");
+      }
+  va_end (args);
+}
+
+/* Runtime error will  print a message and stop the machine. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+rt_error (char *mesg, ...)
+#else
+void
+rt_error (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_error (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+
+  fprintf (stderr, "Runtime error (func=%s, adr=%d): ",
+          f_names[pc.pc_func], pc.pc_addr);
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vfprintf (stderr, mesg, args);
+  va_end (args);
+  
+  fprintf (stderr, "\n");
+  runtime_error = TRUE;
+}
+
+
+/* A runtime warning tells of some action taken by the processor that
+   may change the program execution but was not enough of a problem
+   to stop the execution. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+rt_warn (char *mesg, ...)
+#else
+void
+rt_warn (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_warn (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+
+  fprintf (stderr, "Runtime warning (func=%s, adr=%d): ",
+          f_names[pc.pc_func], pc.pc_addr);
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vfprintf (stderr, mesg, args);
+  va_end (args);
+
+  fprintf (stderr, "\n");
+}
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..ebb9e34
--- /dev/null
@@ -0,0 +1,81 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define to empty if the keyword does not work.  */
+#undef const
+
+/* Define if you don't have vprintf but do have _doprnt.  */
+#undef HAVE_DOPRNT
+
+/* Define if you have the vprintf function.  */
+#undef HAVE_VPRINTF
+
+/* Define if on MINIX.  */
+#undef _MINIX
+
+/* 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 to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+#undef YYTEXT_POINTER
+
+/* VERSION number for DC target*/
+#undef DC_VERSION
+
+/* COPYRIGHT notice for DC target */
+#undef DC_COPYRIGHT
+
+/* COPYRIGHT notice for BC target */
+#undef BC_COPYRIGHT
+
+/* Define to use the readline library. */
+#undef READLINE
+
+/* Define to use the BSD libedit library. */
+#undef LIBEDIT
+
+/* Define to `size_t' if <sys/types.h> and <stddef.h> don't define.  */
+#undef ptrdiff_t
+
+/* Define if you have the isgraph function.  */
+#undef HAVE_ISGRAPH
+
+/* Define if you have the setvbuf function.  */
+#undef HAVE_SETVBUF
+
+/* Define if you have the <lib.h> header file.  */
+#undef HAVE_LIB_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <stdarg.h> header file.  */
+#undef HAVE_STDARG_H
+
+/* Define if you have the <stddef.h> header file.  */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <unistd.h> header file.  */
+#undef HAVE_UNISTD_H
+
+/* Name of package */
+#undef PACKAGE
+
+/* Version number of package */
+#undef VERSION
+
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..e5fc7d9
--- /dev/null
+++ b/configure
@@ -0,0 +1,2656 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --with-pkg              use software installed in /usr/pkg tree"
+ac_help="$ac_help
+  --with-libedit          support fancy BSD command input 
+editing"
+ac_help="$ac_help
+  --with-readline         support fancy command input editing"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+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'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+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
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # 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 ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$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" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) 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)
+    # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --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
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$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)
+    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 ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    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 "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# 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
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=doc/bc.1
+
+# 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_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  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 "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# 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 "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# 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
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:563: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+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 "$ac_t""$INSTALL" 1>&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_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+echo "configure:616: checking whether build environment is sane" >&5
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# 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 conftestfile 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftestfile`
+   fi
+   if test "$*" != "X $srcdir/configure conftestfile" \
+      && test "$*" != "X conftestfile $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 "configure: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" 1>&2; exit 1; }
+   fi
+
+   test "$2" = conftestfile
+   )
+then
+   # Ok.
+   :
+else
+   { echo "configure: error: newly created file is older than distributed files!
+Check your system clock" 1>&2; exit 1; }
+fi
+rm -f conftest*
+echo "$ac_t""yes" 1>&6
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+  rm -f conftestsed
+fi
+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"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:673: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 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 conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+PACKAGE="bc"
+
+VERSION="1.06"
+
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+  { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+fi
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+echo "configure:719: checking for working aclocal" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (aclocal --version) < /dev/null > /dev/null 2>&1; then
+   ACLOCAL=aclocal
+   echo "$ac_t""found" 1>&6
+else
+   ACLOCAL="$missing_dir/missing aclocal"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+echo "configure:732: checking for working autoconf" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoconf --version) < /dev/null > /dev/null 2>&1; then
+   AUTOCONF=autoconf
+   echo "$ac_t""found" 1>&6
+else
+   AUTOCONF="$missing_dir/missing autoconf"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working automake""... $ac_c" 1>&6
+echo "configure:745: checking for working automake" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (automake --version) < /dev/null > /dev/null 2>&1; then
+   AUTOMAKE=automake
+   echo "$ac_t""found" 1>&6
+else
+   AUTOMAKE="$missing_dir/missing automake"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+echo "configure:758: checking for working autoheader" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (autoheader --version) < /dev/null > /dev/null 2>&1; then
+   AUTOHEADER=autoheader
+   echo "$ac_t""found" 1>&6
+else
+   AUTOHEADER="$missing_dir/missing autoheader"
+   echo "$ac_t""missing" 1>&6
+fi
+
+echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+echo "configure:771: checking for working makeinfo" >&5
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf.  Sigh.
+if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
+   MAKEINFO=makeinfo
+   echo "$ac_t""found" 1>&6
+else
+   MAKEINFO="$missing_dir/missing makeinfo"
+   echo "$ac_t""missing" 1>&6
+fi
+
+
+
+
+
+
+cat >> confdefs.h <<\EOF
+#define DC_VERSION "1.3"
+EOF
+
+cat >> confdefs.h <<EOF
+#define BC_COPYRIGHT  "Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc."
+EOF
+
+cat >> confdefs.h <<EOF
+#define DC_COPYRIGHT  "Copyright 1994, 1997, 1998, 2000 Free Software Foundation, Inc."
+EOF
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:804: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:834: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+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 $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:885: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:917: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 928 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:933: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:959: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:964: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:973: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:992: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&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 $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1024: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 1039 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1045: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 1056 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1062: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1073 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1079: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
+echo "configure:1105: checking for minix/config.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1110 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  MINIX=yes
+else
+  echo "$ac_t""no" 1>&6
+MINIX=
+fi
+
+if test "$MINIX" = yes; then
+  cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+  cat >> confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+  cat >> confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+
+missing_dir=`cd $ac_aux_dir && pwd`
+for ac_prog in flex lex
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1159: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=""$missing_dir/missing flex""
+
+# Extract the first word of "flex", so it can be a program name with args.
+set dummy flex; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1192: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="flex"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$LEXLIB"
+then
+  case "$LEX" in
+  flex*) ac_lib=fl ;;
+  *) ac_lib=l ;;
+  esac
+  echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+echo "configure:1226: checking for yywrap in -l$ac_lib" >&5
+ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-l$ac_lib  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1234 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char yywrap();
+
+int main() {
+yywrap()
+; return 0; }
+EOF
+if { (eval echo configure:1245: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LEXLIB="-l$ac_lib"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking lex output file root""... $ac_c" 1>&6
+echo "configure:1268: checking lex output file root" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_root'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # The minimal lex program is just a single line: %%.  But some broken lexes
+# (Solaris, I think it was) want two %% lines, so accommodate them.
+echo '%%
+%%' | $LEX
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  { echo "configure: error: cannot find output from $LEX; giving up" 1>&2; exit 1; }
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_root" 1>&6
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+echo $ac_n "checking whether yytext is a pointer""... $ac_c" 1>&6
+echo "configure:1289: checking whether yytext is a pointer" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_lex_yytext_pointer'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+echo 'extern char *yytext;' >>$LEX_OUTPUT_ROOT.c
+ac_save_LIBS="$LIBS"
+LIBS="$LIBS $LEXLIB"
+cat > conftest.$ac_ext <<EOF
+#line 1301 "configure"
+#include "confdefs.h"
+`cat $LEX_OUTPUT_ROOT.c`
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_prog_lex_yytext_pointer=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+rm -f "${LEX_OUTPUT_ROOT}.c"
+
+fi
+
+echo "$ac_t""$ac_cv_prog_lex_yytext_pointer" 1>&6
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+  cat >> confdefs.h <<\EOF
+#define YYTEXT_POINTER 1
+EOF
+
+fi
+
+for ac_prog in 'bison -y' byacc
+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 $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1334: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_YACC="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+  echo "$ac_t""$YACC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+# 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
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1376: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    IFS="${IFS=        }"; ac_save_IFS="$IFS"; IFS=":"
+  for ac_dir in $PATH; do
+    # Account for people who put trailing slashes in PATH elements.
+    case "$ac_dir/" in
+    /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+    *)
+      # OSF1 and SCO ODT 3.0 have their own names for install.
+      # Don't use installbsd from OSF since it installs stuff as root
+      # by default.
+      for ac_prog in ginstall scoinst install; do
+        if test -f $ac_dir/$ac_prog; then
+         if test $ac_prog = install &&
+            grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         else
+           ac_cv_path_install="$ac_dir/$ac_prog -c"
+           break 2
+         fi
+       fi
+      done
+      ;;
+    esac
+  done
+  IFS="$ac_save_IFS"
+
+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 "$ac_t""$INSTALL" 1>&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_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1431: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:1459: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 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 conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+for ac_hdr in stdarg.h stddef.h stdlib.h string.h limits.h unistd.h lib.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1490: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1495 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1500: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1527: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1532 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* 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;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1581: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_const=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+  cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1602: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1607 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1615: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1632 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  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 <<EOF
+#line 1650 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  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 <<EOF
+#line 1671 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#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); }
+
+EOF
+if { (eval echo configure:1682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:1706: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1711 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking for ptrdiff_t""... $ac_c" 1>&6
+echo "configure:1739: checking for ptrdiff_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_ptrdiff_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1744 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])ptrdiff_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_ptrdiff_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_ptrdiff_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_ptrdiff_t" 1>&6
+if test $ac_cv_type_ptrdiff_t = no; then
+  cat >> confdefs.h <<\EOF
+#define ptrdiff_t size_t
+EOF
+
+fi
+
+
+echo $ac_n "checking for vprintf""... $ac_c" 1>&6
+echo "configure:1773: checking for vprintf" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1778 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char vprintf(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char vprintf();
+
+int main() {
+
+/* 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_vprintf) || defined (__stub___vprintf)
+choke me
+#else
+vprintf();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_vprintf=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_vprintf=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<\EOF
+#define HAVE_VPRINTF 1
+EOF
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test "$ac_cv_func_vprintf" != yes; then
+echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
+echo "configure:1825: checking for _doprnt" >&5
+if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1830 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char _doprnt(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char _doprnt();
+
+int main() {
+
+/* 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
+_doprnt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1853: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func__doprnt=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func__doprnt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<\EOF
+#define HAVE_DOPRNT 1
+EOF
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_func in isgraph setvbuf
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1880: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1885 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* 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();
+
+int main() {
+
+/* 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
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+# Check whether --with-pkg or --without-pkg was given.
+if test "${with_pkg+set}" = set; then
+  withval="$with_pkg"
+  
+   CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
+   LDFLAGS="$LDFLAGS -L/usr/pkg/lib"
+   echo Using /usr/pkg/include and /usr/pkg/lib
+
+fi
+
+
+bcle=n
+# Check whether --with-libedit or --without-libedit was given.
+if test "${with_libedit+set}" = set; then
+  withval="$with_libedit"
+  
+   echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6
+echo "configure:1950: checking for tgetent in -ltermcap" >&5
+ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ltermcap  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1958 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:1969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  TERMLIB=-ltermcap
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+   LDSAVE=$LDFLAGS
+   LDFLAGS="$LDFLAGS $TERMLIB"
+   echo $ac_n "checking for el_gets in -ledit""... $ac_c" 1>&6
+echo "configure:1992: checking for el_gets in -ledit" >&5
+ac_lib_var=`echo edit'_'el_gets | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ledit  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2000 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char el_gets();
+
+int main() {
+el_gets()
+; return 0; }
+EOF
+if { (eval echo configure:2011: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  ac_safe=`echo "histedit.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for histedit.h""... $ac_c" 1>&6
+echo "configure:2028: checking for histedit.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2033 "configure"
+#include "confdefs.h"
+#include <histedit.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2038: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  READLINELIB="-ledit $TERMLIB";bcle=y
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  echo "$ac_t""no" 1>&6
+READLINELIB=""
+fi
+
+   if test "$bcle" = "y"; then
+     echo Using the libedit library.
+     cat >> confdefs.h <<\EOF
+#define LIBEDIT 1
+EOF
+
+   fi
+   LDFLAGS=$LDSAVE
+
+fi
+
+bcrl=n
+# Check whether --with-readline or --without-readline was given.
+if test "${with_readline+set}" = set; then
+  withval="$with_readline"
+  
+   echo $ac_n "checking for tparm in -lncurses""... $ac_c" 1>&6
+echo "configure:2082: checking for tparm in -lncurses" >&5
+ac_lib_var=`echo ncurses'_'tparm | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lncurses  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2090 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char tparm();
+
+int main() {
+tparm()
+; return 0; }
+EOF
+if { (eval echo configure:2101: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  TERMLIB=-lncurses
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6
+echo "configure:2120: checking for tgetent in -ltermcap" >&5
+ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ltermcap  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2128 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char tgetent();
+
+int main() {
+tgetent()
+; return 0; }
+EOF
+if { (eval echo configure:2139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  TERMLIB=-ltermcap
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+   LDSAVE=$LDFLAGS
+   LDFLAGS="$LDFLAGS $TERMLIB"
+   echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
+echo "configure:2164: checking for readline in -lreadline" >&5
+ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lreadline  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2172 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char readline();
+
+int main() {
+readline()
+; return 0; }
+EOF
+if { (eval echo configure:2183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  ac_safe=`echo "readline/readline.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for readline/readline.h""... $ac_c" 1>&6
+echo "configure:2200: checking for readline/readline.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2205 "configure"
+#include "confdefs.h"
+#include <readline/readline.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2210: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  READLINELIB="-lreadline $TERMLIB";bcrl=y
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  echo "$ac_t""no" 1>&6
+READLINELIB=""
+fi
+
+   if test "$bcrl" = "y" ; then
+     echo Using the readline library.
+     cat >> confdefs.h <<\EOF
+#define READLINE 1
+EOF
+
+   fi
+   LDFLAGS=$LDSAVE
+
+fi
+
+
+if test "$LEX" = "flex" ; then
+ LEX="flex -I8"
+else
+ if test "$bcrl" = "y" ; then
+  echo "configure: warning: readline works only with flex." 1>&2
+ fi
+fi
+
+if test "$bcrl" = "y" -a "$bcle" = "y" ; then
+  { echo "configure: error: Can not use both readline and libedit.  Aborting." 1>&2; exit 1; }
+fi
+
+if test "$LEX" = "lex" -a `uname -s` = "SunOS" ; then
+  LEXLIB=""
+  echo "SunOS using lex does not have a -ll."
+fi
+
+
+if test "$program_transform_name" = s,x,x,; then
+  program_transform_name=
+else
+  # Double any \ or $.  echo might interpret backslashes.
+  cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+  program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+  rm -f conftestsed
+fi
+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"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# 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 \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile bc/Makefile dc/Makefile doc/Makefile lib/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@PACKAGE@%$PACKAGE%g
+s%@VERSION@%$VERSION%g
+s%@ACLOCAL@%$ACLOCAL%g
+s%@AUTOCONF@%$AUTOCONF%g
+s%@AUTOMAKE@%$AUTOMAKE%g
+s%@AUTOHEADER@%$AUTOHEADER%g
+s%@MAKEINFO@%$MAKEINFO%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@LEX@%$LEX%g
+s%@LEXLIB@%$LEXLIB%g
+s%@LEX_OUTPUT_ROOT@%$LEX_OUTPUT_ROOT%g
+s%@YACC@%$YACC%g
+s%@RANLIB@%$RANLIB%g
+s%@READLINELIB@%$READLINELIB%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# 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_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # 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" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile bc/Makefile dc/Makefile doc/Makefile lib/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  case "$ac_given_INSTALL" in
+  [/$]*) INSTALL="$ac_given_INSTALL" ;;
+  *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# 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='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  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.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# 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.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..dfa8d68
--- /dev/null
@@ -0,0 +1,89 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(doc/bc.1)
+AM_INIT_AUTOMAKE("bc", "1.06")
+AM_CONFIG_HEADER(config.h)
+
+AC_DEFINE(DC_VERSION,"1.3")
+AC_DEFINE_UNQUOTED(BC_COPYRIGHT, dnl
+ ["Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc."])
+AC_DEFINE_UNQUOTED(DC_COPYRIGHT, dnl
+ ["Copyright 1994, 1997, 1998, 2000 Free Software Foundation, Inc."])
+
+AC_PROG_CC
+AC_MINIX
+dnl AC_ISC_POSIX
+
+AM_PROG_LEX
+AC_PROG_YACC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+AC_PROG_MAKE_SET
+
+AC_CHECK_HEADERS(stdarg.h stddef.h stdlib.h string.h limits.h unistd.h lib.h)
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(ptrdiff_t, size_t)
+
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(isgraph setvbuf)
+
+AC_ARG_WITH(pkg,[  --with-pkg              use software installed in /usr/pkg tree], [
+   CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
+   LDFLAGS="$LDFLAGS -L/usr/pkg/lib"
+   echo Using /usr/pkg/include and /usr/pkg/lib
+])
+
+bcle=n
+AC_ARG_WITH(libedit,[  --with-libedit          support fancy BSD command input 
+editing], [
+   AC_CHECK_LIB(termcap,tgetent,TERMLIB=-ltermcap)
+   LDSAVE=$LDFLAGS
+   LDFLAGS="$LDFLAGS $TERMLIB"
+   AC_CHECK_LIB(edit,el_gets,
+      [AC_CHECK_HEADER(histedit.h,
+      READLINELIB="-ledit $TERMLIB";bcle=y)],
+      READLINELIB="")
+   if test "$bcle" = "y"; then
+     echo Using the libedit library.
+     AC_DEFINE(LIBEDIT,1)
+   fi
+   LDFLAGS=$LDSAVE
+])
+bcrl=n
+AC_ARG_WITH(readline,[  --with-readline         support fancy command input editing], [
+   AC_CHECK_LIB(ncurses,tparm,TERMLIB=-lncurses,
+     AC_CHECK_LIB(termcap,tgetent,TERMLIB=-ltermcap))
+   LDSAVE=$LDFLAGS
+   LDFLAGS="$LDFLAGS $TERMLIB"
+   AC_CHECK_LIB(readline,readline,
+      [AC_CHECK_HEADER(readline/readline.h,
+      READLINELIB="-lreadline $TERMLIB";bcrl=y)],
+      READLINELIB="")
+   if test "$bcrl" = "y" ; then
+     echo Using the readline library.
+     AC_DEFINE(READLINE,1)
+   fi
+   LDFLAGS=$LDSAVE
+])
+
+if test "$LEX" = "flex" ; then
+ LEX="flex -I -8"
+else
+ if test "$bcrl" = "y" ; then
+  AC_MSG_WARN(readline works only with flex.)
+ fi
+fi
+
+if test "$bcrl" = "y" -a "$bcle" = "y" ; then
+  AC_MSG_ERROR(Can not use both readline and libedit.  Aborting.)
+fi
+
+if test "$LEX" = "lex" -a `uname -s` = "SunOS" ; then
+  LEXLIB=""
+  echo "SunOS using lex does not have a -ll."
+fi
+
+AC_SUBST(READLINELIB)
+AC_ARG_PROGRAM
+AC_OUTPUT(Makefile bc/Makefile dc/Makefile doc/Makefile lib/Makefile)
diff --git a/dc/Makefile.am b/dc/Makefile.am
new file mode 100644 (file)
index 0000000..99164ba
--- /dev/null
@@ -0,0 +1,14 @@
+## Process this file with automake to produce Makefile.in
+bin_PROGRAMS = dc
+
+dc_SOURCES = dc.c misc.c eval.c stack.c array.c numeric.c string.c
+noinst_HEADERS = dc.h dc-proto.h dc-regdef.h
+
+INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../h
+LDADD = ../lib/libbc.a
+
+MAINTAINERCLEANFILES = Makefile.in
+
+CFLAGS = @CFLAGS@ -Wall -funsigned-char
+
+$(PROGRAMS): $(LDADD)
diff --git a/dc/Makefile.in b/dc/Makefile.in
new file mode 100644 (file)
index 0000000..0772dd6
--- /dev/null
@@ -0,0 +1,296 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+LEX = @LEX@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+READLINELIB = @READLINELIB@
+VERSION = @VERSION@
+YACC = @YACC@
+
+bin_PROGRAMS = dc
+
+dc_SOURCES = dc.c misc.c eval.c stack.c array.c numeric.c string.c
+noinst_HEADERS = dc.h dc-proto.h dc-regdef.h
+
+INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../h
+LDADD = ../lib/libbc.a
+
+MAINTAINERCLEANFILES = Makefile.in
+
+CFLAGS = @CFLAGS@ -Wall -funsigned-char
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+dc_OBJECTS =  dc.o misc.o eval.o stack.o array.o numeric.o string.o
+dc_LDADD = $(LDADD)
+dc_DEPENDENCIES =  ../lib/libbc.a
+dc_LDFLAGS = 
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+HEADERS =  $(noinst_HEADERS)
+
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(dc_SOURCES)
+OBJECTS = $(dc_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps dc/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+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 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+            $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       list='$(bin_PROGRAMS)'; for p in $$list; do \
+         rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+       done
+
+.c.o:
+       $(COMPILE) -c $<
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+dc: $(dc_OBJECTS) $(dc_DEPENDENCIES)
+       @rm -f dc
+       $(LINK) $(dc_LDFLAGS) $(dc_OBJECTS) $(dc_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = dc
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+array.o: array.c ../config.h dc.h dc-proto.h dc-regdef.h
+dc.o: dc.c ../config.h ../h/getopt.h dc.h dc-proto.h
+eval.o: eval.c ../config.h dc.h dc-proto.h
+misc.o: misc.c ../config.h ../h/getopt.h dc.h dc-proto.h
+numeric.o: numeric.c ../config.h ../h/number.h dc.h dc-proto.h
+stack.o: stack.c ../config.h dc.h dc-proto.h dc-regdef.h
+string.o: string.c ../config.h dc.h dc-proto.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(HEADERS)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+       $(mkinstalldirs)  $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
+               mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-binPROGRAMS clean-compile clean-tags clean-generic \
+               mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-binPROGRAMS distclean-compile distclean-tags \
+               distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-binPROGRAMS \
+               maintainer-clean-compile maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+$(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:
diff --git a/dc/array.c b/dc/array.c
new file mode 100644 (file)
index 0000000..d97f716
--- /dev/null
@@ -0,0 +1,122 @@
+/* 
+ * implement arrays for dc
+ *
+ * Copyright (C) 1994, 1997, 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, you can either send email to this
+ * program's author (see below) or write to:
+ *
+ *    The Free Software Foundation, Inc.
+ *    59 Temple Place, Suite 330
+ *    Boston, MA 02111 USA
+ */
+
+/* This module is the only one that knows what arrays look like. */
+
+#include "config.h"
+
+#include <stdio.h>     /* "dc-proto.h" wants this */
+#ifdef HAVE_STDLIB_H
+/* get size_t definition from "almost ANSI" compiling environments. */
+#include <stdlib.h>
+#endif
+#include "dc.h"
+#include "dc-proto.h"
+#include "dc-regdef.h"
+
+/* what's most useful: quick access or sparse arrays? */
+/* I'll go with sparse arrays for now */
+struct dc_array {
+       int Index;
+       dc_data value;
+       struct dc_array *next;
+};
+
+
+/* initialize the arrays */
+void
+dc_array_init DC_DECLVOID()
+{
+}
+
+/* store value into array_id[Index] */
+void
+dc_array_set DC_DECLARG((array_id, Index, value))
+       int array_id DC_DECLSEP
+       int Index DC_DECLSEP
+       dc_data value DC_DECLEND
+{
+       struct dc_array *cur;
+       struct dc_array *prev=NULL;
+       struct dc_array *newentry;
+
+       cur = dc_get_stacked_array(array_id);
+       while (cur && cur->Index < Index){
+               prev = cur;
+               cur = cur->next;
+       }
+       if (cur && cur->Index == Index){
+               if (cur->value.dc_type == DC_NUMBER)
+                       dc_free_num(&cur->value.v.number);
+               else if (cur->value.dc_type == DC_STRING)
+                       dc_free_str(&cur->value.v.string);
+               else
+                       dc_garbage(" in array", array_id);
+               cur->value = value;
+       }else{
+               newentry = dc_malloc(sizeof *newentry);
+               newentry->Index = Index;
+               newentry->value = value;
+               newentry->next = cur;
+               if (prev)
+                       prev->next = newentry;
+               else
+                       dc_set_stacked_array(array_id, newentry);
+       }
+}
+
+/* retrieve a dup of a value from array_id[Index] */
+/* A zero value is returned if the specified value is unintialized. */
+dc_data
+dc_array_get DC_DECLARG((array_id, Index))
+       int array_id DC_DECLSEP
+       int Index DC_DECLEND
+{
+       struct dc_array *cur;
+
+       for (cur=dc_get_stacked_array(array_id); cur; cur=cur->next)
+               if (cur->Index == Index)
+                       return dc_dup(cur->value);
+       return dc_int2data(0);
+}
+
+/* free an array chain */
+void
+dc_array_free DC_DECLARG((a_head))
+       struct dc_array *a_head DC_DECLEND
+{
+       struct dc_array *cur;
+       struct dc_array *next;
+
+       for (cur=a_head; cur; cur=next) {
+               next = cur->next;
+               if (cur->value.dc_type == DC_NUMBER)
+                       dc_free_num(&cur->value.v.number);
+               else if (cur->value.dc_type == DC_STRING)
+                       dc_free_str(&cur->value.v.string);
+               else
+                       dc_garbage("in stack", -1);
+               free(cur);
+       }
+}
diff --git a/dc/dc-proto.h b/dc/dc-proto.h
new file mode 100644 (file)
index 0000000..f0ac28b
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * prototypes of all externally visible dc functions
+ * 
+ * Copyright (C) 1994, 1997, 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, you can either send email to this
+ * program's author (see below) or write to:
+ *
+ *    The Free Software Foundation, Inc.
+ *    59 Temple Place, Suite 330
+ *    Boston, MA 02111 USA
+ */
+
+extern const char *dc_str2charp DC_PROTO((dc_str));
+extern const char *dc_system DC_PROTO((const char *));
+extern void *dc_malloc DC_PROTO((size_t));
+extern struct dc_array *dc_get_stacked_array DC_PROTO((int));
+
+extern void dc_array_set DC_PROTO((int, int, dc_data));
+extern void dc_array_free DC_PROTO((struct dc_array *));
+extern void dc_array_init DC_PROTO((void));
+extern void dc_binop DC_PROTO((int (*)(dc_num, dc_num, int, dc_num *), int));
+extern void dc_binop2 DC_PROTO((int (*)(dc_num, dc_num, int,
+                                                               dc_num *, dc_num *), int));
+extern void dc_triop DC_PROTO((int (*)(dc_num, dc_num, dc_num, int,
+                                                               dc_num *), int));
+extern void dc_clear_stack DC_PROTO((void));
+extern void dc_dump_num(dc_num, dc_discard);
+extern void dc_free_num DC_PROTO((dc_num *));
+extern void dc_free_str DC_PROTO((dc_str *));
+extern void dc_garbage DC_PROTO((const char *, int));
+extern void dc_math_init DC_PROTO((void));
+extern void dc_memfail DC_PROTO((void));
+extern void dc_out_num DC_PROTO((dc_num, int, dc_newline, dc_discard));
+extern void dc_out_str DC_PROTO((dc_str, dc_newline, dc_discard));
+extern void dc_print DC_PROTO((dc_data, int, dc_newline, dc_discard));
+extern void dc_printall DC_PROTO((int));
+extern void dc_push DC_PROTO((dc_data));
+extern void dc_register_init DC_PROTO((void));
+extern void dc_register_push DC_PROTO((int, dc_data));
+extern void dc_register_set DC_PROTO((int, dc_data));
+extern void dc_set_stacked_array DC_PROTO((int, struct dc_array *));
+extern void dc_show_id DC_PROTO((FILE *, int, const char *));
+extern void dc_string_init DC_PROTO((void));
+
+extern int  dc_cmpop DC_PROTO((void));
+extern int  dc_compare DC_PROTO((dc_num, dc_num));
+extern int  dc_evalfile DC_PROTO((FILE *));
+extern int  dc_evalstr DC_PROTO((dc_data));
+extern int  dc_num2int DC_PROTO((dc_num, dc_discard));
+extern int  dc_numlen DC_PROTO((dc_num));
+extern int  dc_pop DC_PROTO((dc_data *));
+extern int  dc_register_get DC_PROTO((int, dc_data *));
+extern int  dc_register_pop DC_PROTO((int, dc_data *));
+extern int  dc_tell_length DC_PROTO((dc_data, dc_discard));
+extern int  dc_tell_scale DC_PROTO((dc_num, dc_discard));
+extern int  dc_tell_stackdepth DC_PROTO((void));
+extern int  dc_top_of_stack DC_PROTO((dc_data *));
+
+extern size_t dc_strlen DC_PROTO((dc_str));
+
+extern dc_data dc_array_get DC_PROTO((int, int));
+extern dc_data dc_dup DC_PROTO((dc_data));
+extern dc_data dc_dup_num DC_PROTO((dc_num));
+extern dc_data dc_dup_str DC_PROTO((dc_str));
+extern dc_data dc_getnum DC_PROTO((int (*)(void), int, int *));
+extern dc_data dc_int2data DC_PROTO((int));
+extern dc_data dc_makestring DC_PROTO((const char *, size_t));
+extern dc_data dc_readstring DC_PROTO((FILE *, int , int));
+
+extern int dc_add DC_PROTO((dc_num, dc_num, int, dc_num *));
+extern int dc_div DC_PROTO((dc_num, dc_num, int, dc_num *));
+extern int dc_divrem DC_PROTO((dc_num, dc_num, int, dc_num *, dc_num *));
+extern int dc_exp DC_PROTO((dc_num, dc_num, int, dc_num *));
+extern int dc_modexp DC_PROTO((dc_num, dc_num, dc_num, int, dc_num *));
+extern int dc_mul DC_PROTO((dc_num, dc_num, int, dc_num *));
+extern int dc_rem DC_PROTO((dc_num, dc_num, int, dc_num *));
+extern int dc_sub DC_PROTO((dc_num, dc_num, int, dc_num *));
+extern int dc_sqrt DC_PROTO((dc_num, int, dc_num *));
diff --git a/dc/dc-regdef.h b/dc/dc-regdef.h
new file mode 100644 (file)
index 0000000..540268c
--- /dev/null
@@ -0,0 +1,43 @@
+/* 
+ * definitions for dc's "register" declarations
+ *
+ * Copyright (C) 1994 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 author (see below) or write to:
+ *
+ *    The Free Software Foundation, Inc.
+ *    59 Temple Place, Suite 330
+ *    Boston, MA 02111 USA
+ */
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>   /* UCHAR_MAX */
+#endif
+
+/* determine how many register stacks there are */
+#ifndef DC_REGCOUNT
+# ifndef UCHAR_MAX
+#  define DC_REGCOUNT 256
+# else
+#  define DC_REGCOUNT (UCHAR_MAX+1)
+# endif
+#endif /* not DC_REGCOUNT */
+
+/* efficiency hack for masking arbritrary integers to 0..(DC_REGCOUNT-1) */
+#if (DC_REGCOUNT & (DC_REGCOUNT-1)) == 0       /* DC_REGCOUNT is power of 2 */
+# define regmap(r)     ((r) & (DC_REGCOUNT-1))
+#else
+# define regmap(r)     ((r) % DC_REGCOUNT)
+#endif
diff --git a/dc/dc.c b/dc/dc.c
new file mode 100644 (file)
index 0000000..a72644c
--- /dev/null
+++ b/dc/dc.c
@@ -0,0 +1,183 @@
+/* 
+ * implement the "dc" Desk Calculator language.
+ *
+ * Copyright (C) 1994, 1997, 1998, 2000 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 author (see below) or write to:
+ *   The Free Software Foundation, Inc.
+ *   59 Temple Place, Suite 330
+ *   Boston, MA 02111 USA
+ */
+
+/* Written with strong hiding of implementation details
+ * in their own specialized modules.
+ */
+/* This module contains the argument processing/main functions.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif
+#include <getopt.h>
+#include "dc.h"
+#include "dc-proto.h"
+
+#ifndef EXIT_SUCCESS   /* C89 <stdlib.h> */
+# define EXIT_SUCCESS  0
+#endif
+#ifndef EXIT_FAILURE   /* C89 <stdlib.h> */
+# define EXIT_FAILURE  1
+#endif
+
+const char *progname;  /* basename of program invocation */
+
+static void
+bug_report_info DC_DECLVOID()
+{
+       printf("Email bug reports to:  bug-dc@gnu.org .\n");
+}
+
+static void
+show_version DC_DECLVOID()
+{
+       printf("dc (GNU %s %s) %s\n", PACKAGE, VERSION, DC_VERSION);
+       printf("\n%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", DC_COPYRIGHT); 
+}
+
+/* your generic usage function */
+static void
+usage DC_DECLARG((f))
+       FILE *f DC_DECLEND
+{
+       fprintf(f, "\
+Usage: %s [OPTION] [file ...]\n\
+  -e, --expression=EXPR    evaluate expression\n\
+  -f, --file=FILE          evaluate contents of file\n\
+  -h, --help               display this help and exit\n\
+  -V, --version            output version information and exit\n\
+\n\
+", progname);
+       bug_report_info();
+}
+
+/* returns a pointer to one past the last occurance of c in s,
+ * or s if c does not occur in s.
+ */
+static char *
+r1bindex DC_DECLARG((s, c))
+       char *s DC_DECLSEP
+       int  c DC_DECLEND
+{
+       char *p = strrchr(s, c);
+
+       if (!p)
+               return s;
+       return p + 1;
+}
+
+static void
+try_file(const char *filename)
+{
+       FILE *input;
+
+       if (strcmp(filename, "-") == 0) {
+               input = stdin;
+       } else if ( !(input=fopen(filename, "r")) ) {
+               fprintf(stderr, "Could not open file ");
+               perror(filename);
+               exit(EXIT_FAILURE);
+       }
+       if (dc_evalfile(input))
+               exit(EXIT_FAILURE);
+       if (input != stdin)
+               fclose(input);
+}
+
+\f
+int
+main DC_DECLARG((argc, argv))
+       int  argc DC_DECLSEP
+       char **argv DC_DECLEND
+{
+       static struct option const long_opts[] = {
+               {"expression", required_argument, NULL, 'e'},
+               {"file", required_argument, NULL, 'f'},
+               {"help", no_argument, NULL, 'h'},
+               {"version", no_argument, NULL, 'V'},
+               {NULL, 0, NULL, 0}
+       };
+       int did_eval = 0;
+       int c;
+
+       progname = r1bindex(*argv, '/');
+#ifdef HAVE_SETVBUF
+       /* attempt to simplify interaction with applications such as emacs */
+       (void) setvbuf(stdout, NULL, _IOLBF, 0);
+#endif
+       dc_math_init();
+       dc_string_init();
+       dc_register_init();
+       dc_array_init();
+
+       while ((c = getopt_long(argc, argv, "hVe:f:", long_opts, (int *)0)) != EOF) {
+               switch (c) {
+               case 'e':
+                       {       dc_data string = dc_makestring(optarg, strlen(optarg));
+                               if (dc_evalstr(string))
+                                       return EXIT_SUCCESS;
+                               dc_free_str(&string.v.string);
+                               did_eval = 1;
+                       }
+                       break;
+               case 'f':
+                       try_file(optarg);
+                       did_eval = 1;
+                       break;
+               case 'h':
+                       usage(stdout);
+                       return EXIT_SUCCESS;
+               case 'V':
+                       show_version();
+                       return EXIT_SUCCESS;
+               default:
+                       usage(stderr);
+                       return EXIT_FAILURE;
+               }
+       }
+
+       for (; optind < argc; ++optind) {
+               try_file(argv[optind]);
+               did_eval = 1;
+       }
+       if (!did_eval) {
+               /* if no -e commands and no command files, then eval stdin */
+               if (dc_evalfile(stdin))
+                       return EXIT_FAILURE;
+       }
+       return EXIT_SUCCESS;
+}
diff --git a/dc/dc.h b/dc/dc.h
new file mode 100644 (file)
index 0000000..3300f44
--- /dev/null
+++ b/dc/dc.h
@@ -0,0 +1,82 @@
+/* 
+ * Header file for dc routines
+ *
+ * Copyright (C) 1994, 1997, 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, you can either send email to this
+ * program's author (see below) or write to:
+ *
+ *    The Free Software Foundation, Inc.
+ *    59 Temple Place, Suite 330
+ *    Boston, MA 02111 USA
+ */
+
+#ifndef DC_DEFS_H
+#define DC_DEFS_H
+
+/* 'I' is a command, and bases 17 and 18 are quite
+ * unusual, so we limit ourselves to bases 2 to 16
+ */
+#define DC_IBASE_MAX   16
+
+#define DC_SUCCESS             0
+#define DC_DOMAIN_ERROR        1
+#define DC_FAIL                        2       /* generic failure */
+
+
+#ifndef __STDC__
+# define DC_PROTO(x)                   ()
+# define DC_DECLVOID()                 ()
+# define DC_DECLARG(arglist)   arglist
+# define DC_DECLSEP                            ;
+# define DC_DECLEND                            ;
+#else /* __STDC__ */
+# define DC_PROTO(x)                   x
+# define DC_DECLVOID()                 (void)
+# define DC_DECLARG(arglist)   (
+# define DC_DECLSEP                            ,
+# define DC_DECLEND                            )
+#endif /* __STDC__ */
+
+
+typedef enum {DC_TOSS, DC_KEEP}   dc_discard;
+typedef enum {DC_NONL, DC_WITHNL} dc_newline;
+
+
+/* type discriminant for dc_data */
+typedef enum {DC_UNINITIALIZED, DC_NUMBER, DC_STRING} dc_value_type;
+
+/* only numeric.c knows what dc_num's *really* look like */
+typedef struct dc_number *dc_num;
+
+/* only string.c knows what dc_str's *really* look like */
+typedef struct dc_string *dc_str;
+
+
+/* except for the two implementation-specific modules, all
+ * dc functions only know of this one generic type of object
+ */
+typedef struct {
+       dc_value_type dc_type;  /* discriminant for union */
+       union {
+               dc_num number;
+               dc_str string;
+       } v;
+} dc_data;
+
+
+/* This is dc's only global variable: */
+extern const char *progname;   /* basename of program invocation */
+
+#endif /* not DC_DEFS_H */
diff --git a/dc/eval.c b/dc/eval.c
new file mode 100644 (file)
index 0000000..21592d9
--- /dev/null
+++ b/dc/eval.c
@@ -0,0 +1,682 @@
+/* 
+ * evaluate the dc language, from a FILE* or a string
+ *
+ * Copyright (C) 1994, 1997, 1998, 2000 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 author (see below) or write to:
+ *   The Free Software Foundation, Inc.
+ *   59 Temple Place, Suite 330
+ *   Boston, MA 02111 USA
+ */
+
+/* This is the only module which knows about the dc input language */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+# include <string.h>   /* memchr */
+#else
+# ifdef HAVE_MEMORY_H
+#  include <memory.h>  /* memchr, maybe */
+# else
+#  ifdef HAVE_STRINGS_H
+#   include <strings.h>        /* memchr, maybe */
+#  endif
+#endif
+#endif
+#include "dc.h"
+#include "dc-proto.h"
+
+typedef enum {DC_FALSE, DC_TRUE} dc_boolean;
+
+typedef enum {
+       DC_OKAY = DC_SUCCESS, /* no further intervention needed for this command */
+       DC_EATONE,              /* caller needs to eat the lookahead char */
+       DC_QUIT,                /* quit out of unwind_depth levels of evaluation */
+
+       /* with the following return values, the caller does not have to 
+        * fret about stdin_lookahead's value
+        */
+       DC_INT,                 /* caller needs to parse a dc_num from input stream */
+       DC_STR,                 /* caller needs to parse a dc_str from input stream */
+       DC_SYSTEM,              /* caller needs to run a system() on next input line */
+       DC_COMMENT,             /* caller needs to skip to the next input line */
+       DC_NEGCMP,              /* caller needs to re-call dc_func() with `negcmp' set */
+
+       DC_EOF_ERROR    /* unexpected end of input; abort current eval */
+} dc_status;
+
+static int dc_ibase=10;                /* input base, 2 <= dc_ibase <= DC_IBASE_MAX */
+static int dc_obase=10;                /* output base, 2 <= dc_obase */
+static int dc_scale=0;         /* scale (see user documentaton) */
+
+/* for Quitting evaluations */
+static int unwind_depth=0;
+
+/* if true, active Quit will not exit program */
+static dc_boolean unwind_noexit=DC_FALSE;
+
+/*
+ * Used to synchronize lookahead on stdin for '?' command.
+ * If set to EOF then lookahead is used up.
+ */
+static int stdin_lookahead=EOF;
+
+\f
+/* input_fil and input_str are passed as arguments to dc_getnum */
+
+/* used by the input_* functions: */
+static FILE *input_fil_fp;
+static const char *input_str_string;
+
+/* Since we have a need for two characters of pushback, and
+ * ungetc() only guarantees one, we place the second pushback here
+ */
+static int input_pushback;
+
+/* passed as an argument to dc_getnum */
+static int
+input_fil DC_DECLVOID()
+{
+       if (input_pushback != EOF){
+               int c = input_pushback;
+               input_pushback = EOF;
+               return c;
+       }
+       return getc(input_fil_fp);
+}
+
+/* passed as an argument to dc_getnum */
+static int
+input_str DC_DECLVOID()
+{
+       if (!*input_str_string)
+               return EOF;
+       return *input_str_string++;
+}
+
+\f
+
+/* takes a string and evals it; frees the string when done */
+/* Wrapper around dc_evalstr to avoid duplicating the free call
+ * at all possible return points.
+ */
+static int
+dc_eval_and_free_str DC_DECLARG((string))
+       dc_data string DC_DECLEND
+{
+       dc_status status;
+
+       status = dc_evalstr(string);
+       if (string.dc_type == DC_STRING)
+               dc_free_str(&string.v.string);
+       return status;
+}
+
+\f
+/* dc_func does the grunt work of figuring out what each input
+ * character means; used by both dc_evalstr and dc_evalfile
+ *
+ * c -> the "current" input character under consideration
+ * peekc -> the lookahead input character
+ * negcmp -> negate comparison test (for <,=,> commands)
+ */
+static dc_status
+dc_func DC_DECLARG((c, peekc, negcmp))
+       int c DC_DECLSEP
+       int peekc DC_DECLSEP
+       int negcmp DC_DECLEND
+{
+       /* we occasionally need these for temporary data */
+       /* Despite the GNU coding standards, it is much easier
+        * to have these declared once here, since this function
+        * is just one big switch statement.
+        */
+       dc_data datum;
+       int tmpint;
+
+       switch (c){
+       case '_': case '.':
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
+       case '8': case '9': case 'A': case 'B':
+       case 'C': case 'D': case 'E': case 'F':
+               return DC_INT;
+       case ' ':
+       case '\t':
+       case '\n':
+               /* standard command separators */
+               break;
+
+       case '+':       /* add top two stack elements */
+               dc_binop(dc_add, dc_scale);
+               break;
+       case '-':       /* subtract top two stack elements */
+               dc_binop(dc_sub, dc_scale);
+               break;
+       case '*':       /* multiply top two stack elements */
+               dc_binop(dc_mul, dc_scale);
+               break;
+       case '/':       /* divide top two stack elements */
+               dc_binop(dc_div, dc_scale);
+               break;
+       case '%':
+               /* take the remainder from division of the top two stack elements */
+               dc_binop(dc_rem, dc_scale);
+               break;
+       case '~':
+               /* Do division on the top two stack elements.  Return the
+                * quotient as next-to-top of stack and the remainder as
+                * top-of-stack.
+                */
+               dc_binop2(dc_divrem, dc_scale);
+               break;
+       case '|':
+               /* Consider the top three elements of the stack as (base, exp, mod),
+                * where mod is top-of-stack, exp is next-to-top, and base is
+                * second-from-top. Mod must be non-zero, exp must be non-negative,
+                * and all three must be integers. Push the result of raising
+                * base to the exp power, reduced modulo mod. If we had base in
+                * register b, exp in register e, and mod in register m then this
+                * is conceptually equivalent to "lble^lm%", but it is implemented
+                * in a more efficient manner, and can handle arbritrarily large
+                * values for exp.
+                */
+               dc_triop(dc_modexp, dc_scale);
+               break;
+       case '^':       /* exponientiation of the top two stack elements */
+               dc_binop(dc_exp, dc_scale);
+               break;
+       case '<':
+               /* eval register named by peekc if
+                * less-than holds for top two stack elements
+                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if ( (dc_cmpop() <  0) == !negcmp )
+                       if (dc_register_get(peekc, &datum) == DC_SUCCESS)
+                               if (dc_eval_and_free_str(datum) == DC_QUIT)
+                                       return DC_QUIT;
+               return DC_EATONE;
+       case '=':
+               /* eval register named by peekc if
+                * equal-to holds for top two stack elements
+                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if ( (dc_cmpop() == 0) == !negcmp )
+                       if (dc_register_get(peekc, &datum) == DC_SUCCESS)
+                               if (dc_eval_and_free_str(datum) == DC_QUIT)
+                                       return DC_QUIT;
+               return DC_EATONE;
+       case '>':
+               /* eval register named by peekc if
+                * greater-than holds for top two stack elements
+                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if ( (dc_cmpop() >  0) == !negcmp )
+                       if (dc_register_get(peekc, &datum) == DC_SUCCESS)
+                               if (dc_eval_and_free_str(datum) == DC_QUIT)
+                                       return DC_QUIT;
+               return DC_EATONE;
+       case '?':       /* read a line from standard-input and eval it */
+               if (stdin_lookahead != EOF){
+                       ungetc(stdin_lookahead, stdin);
+                       stdin_lookahead = EOF;
+               }
+               if (dc_eval_and_free_str(dc_readstring(stdin, '\n', '\n')) == DC_QUIT)
+                       return DC_QUIT;
+               return DC_OKAY;
+       case '[':       /* read to balancing ']' into a dc_str */
+               return DC_STR;
+       case '!':       /* read to newline and call system() on resulting string */
+               if (peekc == '<' || peekc == '=' || peekc == '>')
+                       return DC_NEGCMP;
+               return DC_SYSTEM;
+       case '#':       /* comment; skip remainder of current line */
+               return DC_COMMENT;
+
+       case 'a':       /* Convert top of stack to an ascii character. */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       char tmps;
+                       if (datum.dc_type == DC_NUMBER){
+                               tmps = (char) dc_num2int(datum.v.number, DC_TOSS);
+                       }else if (datum.dc_type == DC_STRING){
+                               tmps = *dc_str2charp(datum.v.string);
+                               dc_free_str(&datum.v.string);
+                       }else{
+                               dc_garbage("at top of stack", -1);
+                       }
+                       dc_push(dc_makestring(&tmps, 1));
+               }
+               break;
+       case 'c':       /* clear whole stack */
+               dc_clear_stack();
+               break;
+       case 'd':       /* duplicate the datum on the top of stack */
+               if (dc_top_of_stack(&datum) == DC_SUCCESS)
+                       dc_push(dc_dup(datum));
+               break;
+       case 'f':       /* print list of all stack items */
+               dc_printall(dc_obase);
+               break;
+       case 'i':       /* set input base to value on top of stack */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = 0;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_num2int(datum.v.number, DC_TOSS);
+                       if ( ! (2 <= tmpint  &&  tmpint <= DC_IBASE_MAX) )
+                               fprintf(stderr,
+                                               "%s: input base must be a number \
+between 2 and %d (inclusive)\n",
+                                               progname, DC_IBASE_MAX);
+                       else
+                               dc_ibase = tmpint;
+               }
+               break;
+       case 'k':       /* set scale to value on top of stack */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = -1;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_num2int(datum.v.number, DC_TOSS);
+                       if ( ! (tmpint >= 0) )
+                               fprintf(stderr,
+                                               "%s: scale must be a nonnegative number\n",
+                                               progname);
+                       else
+                               dc_scale = tmpint;
+               }
+               break;
+       case 'l':       /* "load" -- push value on top of register stack named
+                                * by peekc onto top of evaluation stack; does not
+                                * modify the register stack
+                                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if (dc_register_get(peekc, &datum) == DC_SUCCESS)
+                       dc_push(datum);
+               return DC_EATONE;
+       case 'n':       /* print the value popped off of top-of-stack;
+                                * do not add a trailing newline
+                                */
+               if (dc_pop(&datum) == DC_SUCCESS)
+                       dc_print(datum, dc_obase, DC_NONL, DC_TOSS);
+               break;
+       case 'o':       /* set output base to value on top of stack */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = 0;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_num2int(datum.v.number, DC_TOSS);
+                       if ( ! (tmpint > 1) )
+                               fprintf(stderr,
+                                               "%s: output base must be a number greater than 1\n",
+                                               progname);
+                       else
+                               dc_obase = tmpint;
+               }
+               break;
+       case 'p':       /* print the datum on the top of stack,
+                                * with a trailing newline
+                                */
+               if (dc_top_of_stack(&datum) == DC_SUCCESS)
+                       dc_print(datum, dc_obase, DC_WITHNL, DC_KEEP);
+               break;
+       case 'q':       /* quit two levels of evaluation, posibly exiting program */
+               unwind_depth = 1; /* the return below is the first level of returns */
+               unwind_noexit = DC_FALSE;
+               return DC_QUIT;
+       case 'r':       /* rotate (swap) the top two elements on the stack
+                                */
+               if (dc_pop(&datum) == DC_SUCCESS) {
+                       dc_data datum2;
+                       int two_status;
+                       two_status = dc_pop(&datum2);
+                       dc_push(datum);
+                       if (two_status == DC_SUCCESS)
+                               dc_push(datum2);
+               }
+               break;
+       case 's':       /* "store" -- replace top of register stack named
+                                * by peekc with the value popped from the top
+                                * of the evaluation stack
+                                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if (dc_pop(&datum) == DC_SUCCESS)
+                       dc_register_set(peekc, datum);
+               return DC_EATONE;
+       case 'v':       /* replace top of stack with its square root */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       dc_num tmpnum;
+                       if (datum.dc_type != DC_NUMBER){
+                               fprintf(stderr,
+                                               "%s: square root of nonnumeric attempted\n",
+                                               progname);
+                       }else if (dc_sqrt(datum.v.number, dc_scale, &tmpnum) == DC_SUCCESS){
+                               dc_free_num(&datum.v.number);
+                               datum.v.number = tmpnum;
+                               dc_push(datum);
+                       }
+               }
+               break;
+       case 'x':       /* eval the datum popped from top of stack */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       if (datum.dc_type == DC_STRING){
+                               if (dc_eval_and_free_str(datum) == DC_QUIT)
+                                       return DC_QUIT;
+                       }else if (datum.dc_type == DC_NUMBER){
+                               dc_push(datum);
+                       }else{
+                               dc_garbage("at top of stack", -1);
+                       }
+               }
+               break;
+       case 'z':       /* push the current stack depth onto the top of stack */
+               dc_push(dc_int2data(dc_tell_stackdepth()));
+               break;
+
+       case 'I':       /* push the current input base onto the stack */
+               dc_push(dc_int2data(dc_ibase));
+               break;
+       case 'K':       /* push the current scale onto the stack */
+               dc_push(dc_int2data(dc_scale));
+               break;
+       case 'L':       /* pop a value off of register stack named by peekc
+                                * and push it onto the evaluation stack
+                                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if (dc_register_pop(peekc, &datum) == DC_SUCCESS)
+                       dc_push(datum);
+               return DC_EATONE;
+       case 'O':       /* push the current output base onto the stack */
+               dc_push(dc_int2data(dc_obase));
+               break;
+       case 'P':
+               /* Pop the value off the top of a stack.  If it is
+                * a number, dump out the integer portion of its
+                * absolute value as a "base UCHAR_MAX+1" byte stream;
+                * if it is a string, just print it.
+                * In either case, do not append a trailing newline.
+                */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       if (datum.dc_type == DC_NUMBER)
+                               dc_dump_num(datum.v.number, DC_TOSS);
+                       else if (datum.dc_type == DC_STRING)
+                               dc_out_str(datum.v.string, DC_NONL, DC_TOSS);
+                       else
+                               dc_garbage("at top of stack", -1);
+               }
+               break;
+       case 'Q':       /* quit out of top-of-stack nested evals;
+                                * pops value from stack;
+                                * does not exit program (stops short if necessary)
+                                */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       unwind_depth = 0;
+                       unwind_noexit = DC_TRUE;
+                       if (datum.dc_type == DC_NUMBER)
+                               unwind_depth = dc_num2int(datum.v.number, DC_TOSS);
+                       if (unwind_depth-- > 0)
+                               return DC_QUIT;
+                       unwind_depth = 0;       /* paranoia */
+                       fprintf(stderr,
+                                       "%s: Q command requires a number >= 1\n",
+                                       progname);
+               }
+               break;
+#if 0
+       case 'R':       /* pop a value off of the evaluation stack,;
+                                * rotate the top
+                                remaining stack elements that many
+                                * places forward (negative numbers mean rotate
+                                * backward).
+                                */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = 0;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_num2int(datum.v.number, DC_TOSS);
+                       dc_stack_rotate(tmpint);
+               }
+               break;
+#endif
+       case 'S':       /* pop a value off of the evaluation stack
+                                * and push it onto the register stack named by peekc
+                                */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if (dc_pop(&datum) == DC_SUCCESS)
+                       dc_register_push(peekc, datum);
+               return DC_EATONE;
+       case 'X':       /* replace the number on top-of-stack with its scale factor */
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = 0;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_tell_scale(datum.v.number, DC_TOSS);
+                       dc_push(dc_int2data(tmpint));
+               }
+               break;
+       case 'Z':       /* replace the datum on the top-of-stack with its length */
+               if (dc_pop(&datum) == DC_SUCCESS)
+                       dc_push(dc_int2data(dc_tell_length(datum, DC_TOSS)));
+               break;
+
+       case ':':       /* store into array */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = -1;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_num2int(datum.v.number, DC_TOSS);
+                       if (dc_pop(&datum) == DC_SUCCESS){
+                               if (tmpint < 0)
+                                       fprintf(stderr,
+                                                       "%s: array index must be a nonnegative integer\n",
+                                                       progname);
+                               else
+                                       dc_array_set(peekc, tmpint, datum);
+                       }
+               }
+               return DC_EATONE;
+       case ';':       /* retreive from array */
+               if (peekc == EOF)
+                       return DC_EOF_ERROR;
+               if (dc_pop(&datum) == DC_SUCCESS){
+                       tmpint = -1;
+                       if (datum.dc_type == DC_NUMBER)
+                               tmpint = dc_num2int(datum.v.number, DC_TOSS);
+                       if (tmpint < 0)
+                               fprintf(stderr,
+                                               "%s: array index must be a nonnegative integer\n",
+                                               progname);
+                       else
+                               dc_push(dc_array_get(peekc, tmpint));
+               }
+               return DC_EATONE;
+
+       default:        /* What did that user mean? */
+               fprintf(stderr, "%s: ", progname);
+               dc_show_id(stdout, c, " unimplemented\n");
+               break;
+       }
+       return DC_OKAY;
+}
+
+\f
+/* takes a string and evals it */
+int
+dc_evalstr DC_DECLARG((string))
+       dc_data string DC_DECLEND
+{
+       const char *s;
+       const char *end;
+       const char *p;
+       size_t len;
+       int c;
+       int peekc;
+       int count;
+       int negcmp;
+       int next_negcmp = 0;
+
+       if (string.dc_type != DC_STRING){
+               fprintf(stderr,
+                               "%s: eval called with non-string argument\n",
+                               progname);
+               return DC_OKAY;
+       }
+       s = dc_str2charp(string.v.string);
+       end = s + dc_strlen(string.v.string);
+       while (s < end){
+               c = *(const unsigned char *)s++;
+               peekc = EOF;
+               if (s < end)
+                       peekc = *(const unsigned char *)s;
+               negcmp = next_negcmp;
+               next_negcmp = 0;
+               switch (dc_func(c, peekc, negcmp)){
+               case DC_OKAY:
+                       break;
+               case DC_EATONE:
+                       if (peekc != EOF)
+                               ++s;
+                       break;
+               case DC_QUIT:
+                       if (unwind_depth > 0){
+                               --unwind_depth;
+                               return DC_QUIT;
+                       }
+                       return DC_OKAY;
+
+               case DC_INT:
+                       input_str_string = s - 1;
+                       dc_push(dc_getnum(input_str, dc_ibase, &peekc));
+                       s = input_str_string;
+                       if (peekc != EOF)
+                               --s;
+                       break;
+               case DC_STR:
+                       count = 1;
+                       for (p=s; p<end && count>0; ++p)
+                               if (*p == ']')
+                                       --count;
+                               else if (*p == '[')
+                                       ++count;
+                       len = p - s;
+                       dc_push(dc_makestring(s, len-1));
+                       s = p;
+                       break;
+               case DC_SYSTEM:
+                       s = dc_system(s);
+               case DC_COMMENT:
+                       s = memchr(s, '\n', (size_t)(end-s));
+                       if (!s)
+                               s = end;
+                       else
+                               ++s;
+                       break;
+               case DC_NEGCMP:
+                       next_negcmp = 1;
+                       break;
+
+               case DC_EOF_ERROR:
+                       fprintf(stderr, "%s: unexpected EOS\n", progname);
+                       return DC_OKAY;
+               }
+       }
+       return DC_OKAY;
+}
+
+\f
+/* This is the main function of the whole DC program.
+ * Reads the file described by fp, calls dc_func to do
+ * the dirty work, and takes care of dc_func's shortcomings.
+ */
+int
+dc_evalfile DC_DECLARG((fp))
+       FILE *fp DC_DECLEND
+{
+       int c;
+       int peekc;
+       int negcmp;
+       int next_negcmp = 0;
+       dc_data datum;
+
+       stdin_lookahead = EOF;
+       for (c=getc(fp); c!=EOF; c=peekc){
+               peekc = getc(fp);
+               /*
+                * The following if() is the only place where ``stdin_lookahead''
+                * might be set to other than EOF:
+                */
+               if (fp == stdin)
+                       stdin_lookahead = peekc;
+               negcmp = next_negcmp;
+               next_negcmp = 0;
+               switch (dc_func(c, peekc, negcmp)){
+               case DC_OKAY:
+                       if (stdin_lookahead != peekc  &&  fp == stdin)
+                               peekc = getc(fp);
+                       break;
+               case DC_EATONE:
+                       peekc = getc(fp);
+                       break;
+               case DC_QUIT:
+                       if (unwind_noexit != DC_TRUE)
+                               return DC_SUCCESS;
+                       fprintf(stderr,
+                                       "%s: Q command argument exceeded string execution depth\n",
+                                       progname);
+                       if (stdin_lookahead != peekc  &&  fp == stdin)
+                               peekc = getc(fp);
+                       break;
+
+               case DC_INT:
+                       input_fil_fp = fp;
+                       input_pushback = c;
+                       ungetc(peekc, fp);
+                       dc_push(dc_getnum(input_fil, dc_ibase, &peekc));
+                       break;
+               case DC_STR:
+                       ungetc(peekc, fp);
+                       datum = dc_readstring(fp, '[', ']');
+                       dc_push(datum);
+                       peekc = getc(fp);
+                       break;
+               case DC_SYSTEM:
+                       ungetc(peekc, fp);
+                       datum = dc_readstring(stdin, '\n', '\n');
+                       (void)dc_system(dc_str2charp(datum.v.string));
+                       dc_free_str(&datum.v.string);
+                       peekc = getc(fp);
+                       break;
+               case DC_COMMENT:
+                       while (peekc!=EOF && peekc!='\n')
+                               peekc = getc(fp);
+                       if (peekc != EOF)
+                               peekc = getc(fp);
+                       break;
+               case DC_NEGCMP:
+                       next_negcmp = 1;
+                       break;
+
+               case DC_EOF_ERROR:
+                       fprintf(stderr, "%s: unexpected EOF\n", progname);
+                       return DC_FAIL;
+               }
+       }
+       return DC_SUCCESS;
+}
diff --git a/dc/misc.c b/dc/misc.c
new file mode 100644 (file)
index 0000000..fa94de1
--- /dev/null
+++ b/dc/misc.c
@@ -0,0 +1,179 @@
+/* 
+ * misc. functions for the "dc" Desk Calculator language.
+ *
+ * Copyright (C) 1994, 1997, 1998, 2000 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 author (see below) or write to:
+ *   The Free Software Foundation, Inc.
+ *   59 Temple Place, Suite 330
+ *   Boston, MA 02111 USA
+ */
+
+/* This module contains miscelaneous functions that have no
+ * special knowledge of any private data structures.
+ * They could all be moved to their own separate modules, but
+ * are agglomerated here for convenience.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif
+#include <ctype.h>
+#ifndef isgraph
+# ifndef HAVE_ISGRAPH
+#  define isgraph isprint
+# endif
+#endif
+#include <getopt.h>
+#include "dc.h"
+#include "dc-proto.h"
+
+#ifndef EXIT_FAILURE   /* C89 <stdlib.h> */
+# define EXIT_FAILURE  1
+#endif
+
+\f
+/* print an "out of memory" diagnostic and exit program */
+void
+dc_memfail DC_DECLVOID()
+{
+       fprintf(stderr, "%s: out of memory\n", progname);
+       exit(EXIT_FAILURE);
+}
+
+/* malloc or die */
+void *
+dc_malloc DC_DECLARG((len))
+       size_t len DC_DECLEND
+{
+       void *result = malloc(len);
+
+       if (!result)
+               dc_memfail();
+       return result;
+}
+
+\f
+/* print the id in a human-understandable form
+ *  fp is the output stream to place the output on
+ *  id is the name of the register (or command) to be printed
+ *  suffix is a modifier (such as "stack") to be printed
+ */
+void
+dc_show_id DC_DECLARG((fp, id, suffix))
+       FILE *fp DC_DECLSEP
+       int id DC_DECLSEP
+       const char *suffix DC_DECLEND
+{
+       if (isgraph(id))
+               fprintf(fp, "'%c' (%#o)%s", id, id, suffix);
+       else
+               fprintf(fp, "%#o%s", id, suffix);
+}
+
+\f
+/* report that corrupt data has been detected;
+ * use the msg and regid (if nonnegative) to give information
+ * about where the garbage was found,
+ *
+ * will abort() so that a debugger might be used to help find
+ * the bug
+ */
+/* If this routine is called, then there is a bug in the code;
+ * i.e. it is _not_ a data or user error
+ */
+void
+dc_garbage DC_DECLARG((msg, regid))
+       const char *msg DC_DECLSEP
+       int regid DC_DECLEND
+{
+       if (regid < 0) {
+               fprintf(stderr, "%s: garbage %s\n", progname, msg);
+       } else {
+               fprintf(stderr, "%s:%s register ", progname, msg);
+               dc_show_id(stderr, regid, " is garbage\n");
+       }
+       abort();
+}
+
+\f
+/* call system() with the passed string;
+ * if the string contains a newline, terminate the string
+ * there before calling system.
+ * Return a pointer to the first unused character in the string
+ * (i.e. past the '\n' if there was one, to the '\0' otherwise).
+ */
+const char *
+dc_system DC_DECLARG((s))
+       const char *s DC_DECLEND
+{
+       const char *p;
+       char *tmpstr;
+       size_t len;
+
+       p = strchr(s, '\n');
+       if (p) {
+               len = p - s;
+               tmpstr = dc_malloc(len + 1);
+               strncpy(tmpstr, s, len);
+               tmpstr[len] = '\0';
+               system(tmpstr);
+               free(tmpstr);
+               return p + 1;
+       }
+       system(s);
+       return s + strlen(s);
+}
+
+\f
+/* print out the indicated value */
+void
+dc_print DC_DECLARG((value, obase, newline_p, discard_p))
+       dc_data value DC_DECLSEP
+       int obase DC_DECLSEP
+       dc_newline newline_p DC_DECLSEP
+       dc_discard discard_p DC_DECLEND
+{
+       if (value.dc_type == DC_NUMBER) {
+               dc_out_num(value.v.number, obase, newline_p, discard_p);
+       } else if (value.dc_type == DC_STRING) {
+               dc_out_str(value.v.string, newline_p, discard_p);
+       } else {
+               dc_garbage("in data being printed", -1);
+       }
+}
+
+/* return a duplicate of the passed value, regardless of type */
+dc_data
+dc_dup DC_DECLARG((value))
+       dc_data value DC_DECLEND
+{
+       if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING)
+               dc_garbage("in value being duplicated", -1);
+       if (value.dc_type == DC_NUMBER)
+               return dc_dup_num(value.v.number);
+       /*else*/
+       return dc_dup_str(value.v.string);
+}
diff --git a/dc/numeric.c b/dc/numeric.c
new file mode 100644 (file)
index 0000000..78b7eec
--- /dev/null
@@ -0,0 +1,600 @@
+/* 
+ * interface dc to the bc numeric routines
+ *
+ * Copyright (C) 1994, 1997, 1998, 2000 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 author (see below) or write to:
+ *   The Free Software Foundation, Inc.
+ *   59 Temple Place, Suite 330
+ *   Boston, MA 02111 USA
+ */
+
+/* This should be the only module that knows the internals of type dc_num */
+/* In this particular implementation we just slather out some glue and
+ * make use of bc's numeric routines.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#else
+# define UCHAR_MAX ((unsigned char)~0)
+#endif
+#include <stdlib.h>
+#include "number.h"
+#include "dc.h"
+#include "dc-proto.h"
+
+#ifdef __GNUC__
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__-0 >= 7) 
+#  define ATTRIB(x) __attribute__(x)
+# endif
+#endif
+#ifndef ATTRIB
+# define ATTRIB(x)
+#endif
+
+/* Forward prototype */
+static void out_char (int);
+
+/* there is no POSIX standard for dc, so we'll take the GNU definitions */
+int std_only = FALSE;
+
+/* convert an opaque dc_num into a real bc_num */
+#define CastNum(x)     ((bc_num)(x))
+
+/* add two dc_nums, place into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_add DC_DECLARG((a, b, kscale, result))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale ATTRIB((unused)) DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       bc_add(CastNum(a), CastNum(b), (bc_num *)result, 0);
+       return DC_SUCCESS;
+}
+
+/* subtract two dc_nums, place into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_sub DC_DECLARG((a, b, kscale, result))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale ATTRIB((unused)) DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       bc_sub(CastNum(a), CastNum(b), (bc_num *)result, 0);
+       return DC_SUCCESS;
+}
+
+/* multiply two dc_nums, place into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_mul DC_DECLARG((a, b, kscale, result))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       bc_multiply(CastNum(a), CastNum(b), (bc_num *)result, kscale);
+       return DC_SUCCESS;
+}
+
+/* divide two dc_nums, place into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_div DC_DECLARG((a, b, kscale, result))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       if (bc_divide(CastNum(a), CastNum(b), (bc_num *)result, kscale)){
+               fprintf(stderr, "%s: divide by zero\n", progname);
+               return DC_DOMAIN_ERROR;
+       }
+       return DC_SUCCESS;
+}
+
+/* divide two dc_nums, place quotient into *quotient and remainder
+ * into *remainder;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_divrem DC_DECLARG((a, b, kscale, quotient, remainder))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *quotient DC_DECLSEP
+       dc_num *remainder DC_DECLEND
+{
+       bc_init_num((bc_num *)quotient);
+       bc_init_num((bc_num *)remainder);
+       if (bc_divmod(CastNum(a), CastNum(b),
+                                               (bc_num *)quotient, (bc_num *)remainder, kscale)){
+               fprintf(stderr, "%s: divide by zero\n", progname);
+               return DC_DOMAIN_ERROR;
+       }
+       return DC_SUCCESS;
+}
+
+/* place the reminder of dividing a by b into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_rem DC_DECLARG((a, b, kscale, result))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       if (bc_modulo(CastNum(a), CastNum(b), (bc_num *)result, kscale)){
+               fprintf(stderr, "%s: remainder by zero\n", progname);
+               return DC_DOMAIN_ERROR;
+       }
+       return DC_SUCCESS;
+}
+
+int
+dc_modexp DC_DECLARG((base, expo, mod, kscale, result))
+       dc_num base DC_DECLSEP
+       dc_num expo DC_DECLSEP
+       dc_num mod DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       if (bc_raisemod(CastNum(base), CastNum(expo), CastNum(mod),
+                                       (bc_num *)result, kscale)){
+               if (bc_is_zero(CastNum(mod)))
+                       fprintf(stderr, "%s: remainder by zero\n", progname);
+               return DC_DOMAIN_ERROR;
+       }
+       return DC_SUCCESS;
+}
+
+/* place the result of exponentiationg a by b into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_exp DC_DECLARG((a, b, kscale, result))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_init_num((bc_num *)result);
+       bc_raise(CastNum(a), CastNum(b), (bc_num *)result, kscale);
+       return DC_SUCCESS;
+}
+
+/* take the square root of the value, place into *result;
+ * return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
+ */
+int
+dc_sqrt DC_DECLARG((value, kscale, result))
+       dc_num value DC_DECLSEP
+       int kscale DC_DECLSEP
+       dc_num *result DC_DECLEND
+{
+       bc_num tmp;
+
+       tmp = bc_copy_num(CastNum(value));
+       if (!bc_sqrt(&tmp, kscale)){
+               fprintf(stderr, "%s: square root of negative number\n", progname);
+               bc_free_num(&tmp);
+               return DC_DOMAIN_ERROR;
+       }
+       *((bc_num *)result) = tmp;
+       return DC_SUCCESS;
+}
+
+/* compare dc_nums a and b;
+ *  return a negative value if a < b;
+ *  return a positive value if a > b;
+ *  return zero value if a == b
+ */
+int
+dc_compare DC_DECLARG((a, b))
+       dc_num a DC_DECLSEP
+       dc_num b DC_DECLEND
+{
+       return bc_compare(CastNum(a), CastNum(b));
+}
+\f
+/* attempt to convert a dc_num to its corresponding int value
+ * If discard_p is DC_TOSS then deallocate the value after use.
+ */
+int
+dc_num2int DC_DECLARG((value, discard_p))
+       dc_num value DC_DECLSEP
+       dc_discard discard_p DC_DECLEND
+{
+       long result;
+
+       result = bc_num2long(CastNum(value));
+       if (discard_p == DC_TOSS)
+               dc_free_num(&value);
+       return (int)result;
+}
+
+/* convert a C integer value into a dc_num */
+/* For convenience of the caller, package the dc_num
+ * into a dc_data result.
+ */
+dc_data
+dc_int2data DC_DECLARG((value))
+       int value DC_DECLEND
+{
+       dc_data result;
+
+       bc_init_num(&result.v.number);
+       bc_int2num(&result.v.number, value);
+       result.dc_type = DC_NUMBER;
+       return result;
+}
+
+/* get a dc_num from some input stream;
+ *  input is a function which knows how to read the desired input stream
+ *  ibase is the input base (2<=ibase<=DC_IBASE_MAX)
+ *  *readahead will be set to the readahead character consumed while
+ *   looking for the end-of-number
+ */
+/* For convenience of the caller, package the dc_num
+ * into a dc_data result.
+ */
+dc_data
+dc_getnum DC_DECLARG((input, ibase, readahead))
+       int (*input) DC_PROTO((void)) DC_DECLSEP
+       int ibase DC_DECLSEP
+       int *readahead DC_DECLEND
+{
+       bc_num  base;
+       bc_num  result;
+       bc_num  build;
+       bc_num  tmp;
+       bc_num  divisor;
+       dc_data full_result;
+       int             negative = 0;
+       int             digit;
+       int             decimal;
+       int             c;
+
+       bc_init_num(&tmp);
+       bc_init_num(&build);
+       bc_init_num(&base);
+       result = bc_copy_num(_zero_);
+       bc_int2num(&base, ibase);
+       c = (*input)();
+       while (isspace(c))
+               c = (*input)();
+       if (c == '_' || c == '-'){
+               negative = c;
+               c = (*input)();
+       }else if (c == '+'){
+               c = (*input)();
+       }
+       while (isspace(c))
+               c = (*input)();
+       for (;;){
+               if (isdigit(c))
+                       digit = c - '0';
+               else if ('A' <= c && c <= 'F')
+                       digit = 10 + c - 'A';
+               else
+                       break;
+               c = (*input)();
+               bc_int2num(&tmp, digit);
+               bc_multiply(result, base, &result, 0);
+               bc_add(result, tmp, &result, 0);
+       }
+       if (c == '.'){
+               bc_free_num(&build);
+               bc_free_num(&tmp);
+               divisor = bc_copy_num(_one_);
+               build = bc_copy_num(_zero_);
+               decimal = 0;
+               for (;;){
+                       c = (*input)();
+                       if (isdigit(c))
+                               digit = c - '0';
+                       else if ('A' <= c && c <= 'F')
+                               digit = 10 + c - 'A';
+                       else
+                               break;
+                       bc_int2num(&tmp, digit);
+                       bc_multiply(build, base, &build, 0);
+                       bc_add(build, tmp, &build, 0);
+                       bc_multiply(divisor, base, &divisor, 0);
+                       ++decimal;
+               }
+               bc_divide(build, divisor, &build, decimal);
+               bc_add(result, build, &result, 0);
+       }
+       /* Final work. */
+       if (negative)
+               bc_sub(_zero_, result, &result, 0);
+
+       bc_free_num(&tmp);
+       bc_free_num(&build);
+       bc_free_num(&base);
+       if (readahead)
+               *readahead = c;
+       full_result.v.number = (dc_num)result;
+       full_result.dc_type = DC_NUMBER;
+       return full_result;
+}
+
+\f
+/* return the "length" of the number */
+int
+dc_numlen DC_DECLARG((value))
+       dc_num value DC_DECLEND
+{
+       bc_num num = CastNum(value);
+
+       /* is this right??? */
+       return num->n_len + num->n_scale - (*num->n_value == '\0');
+}
+
+/* return the scale factor of the passed dc_num
+ * If discard_p is DC_TOSS then deallocate the value after use.
+ */
+int
+dc_tell_scale DC_DECLARG((value, discard_p))
+       dc_num value DC_DECLSEP
+       dc_discard discard_p DC_DECLEND
+{
+       int kscale;
+
+       kscale = CastNum(value)->n_scale;
+       if (discard_p == DC_TOSS)
+               dc_free_num(&value);
+       return kscale;
+}
+
+\f
+/* initialize the math subsystem */
+void
+dc_math_init DC_DECLVOID()
+{
+       bc_init_numbers();
+}
+\f
+/* print out a dc_num in output base obase to stdout;
+ * if newline_p is DC_WITHNL, terminate output with a '\n';
+ * if discard_p is DC_TOSS then deallocate the value after use
+ */
+void
+dc_out_num DC_DECLARG((value, obase, newline_p, discard_p))
+       dc_num value DC_DECLSEP
+       int obase DC_DECLSEP
+       dc_newline newline_p DC_DECLSEP
+       dc_discard discard_p DC_DECLEND
+{
+       out_char('\0'); /* clear the column counter */
+       bc_out_num(CastNum(value), obase, out_char, 0);
+       if (newline_p == DC_WITHNL)
+               putchar ('\n');
+       if (discard_p == DC_TOSS)
+               dc_free_num(&value);
+}
+
+/* dump out the absolute value of the integer part of a
+ * dc_num as a byte stream, without any line wrapping;
+ * if discard_p is DC_TOSS then deallocate the value after use
+ */
+void
+dc_dump_num DC_DECLARG((dcvalue, discard_p))
+       dc_num dcvalue DC_DECLSEP
+       dc_discard discard_p DC_DECLEND
+{
+       struct digit_stack { int digit; struct digit_stack *link;};
+       struct digit_stack *top_of_stack = NULL;
+       struct digit_stack *cur;
+       struct digit_stack *next;
+       bc_num value;
+       bc_num obase;
+       bc_num digit;
+
+       bc_init_num(&value);
+       bc_init_num(&obase);
+       bc_init_num(&digit);
+
+       /* we only handle the integer portion: */
+       bc_divide(CastNum(dcvalue), _one_, &value, 0);
+       /* we only handle the absolute value: */
+       value->n_sign = PLUS;
+       /* we're done with the dcvalue parameter: */
+       if (discard_p == DC_TOSS)
+               dc_free_num(&dcvalue);
+
+       bc_int2num(&obase, 1+UCHAR_MAX);
+       do {
+               (void) bc_divmod(value, obase, &value, &digit, 0);
+               cur = dc_malloc(sizeof *cur);
+               cur->digit = (int)bc_num2long(digit);
+               cur->link = top_of_stack;
+               top_of_stack = cur;
+       } while (!bc_is_zero(value));
+
+       for (cur=top_of_stack; cur; cur=next) {
+               putchar(cur->digit);
+               next = cur->link;
+               free(cur);
+       }
+
+       bc_free_num(&digit);
+       bc_free_num(&obase);
+       bc_free_num(&value);
+}
+\f
+/* deallocate an instance of a dc_num */
+void
+dc_free_num DC_DECLARG((value))
+       dc_num *value DC_DECLEND
+{
+       bc_free_num((bc_num *)value);
+}
+
+/* return a duplicate of the number in the passed value */
+/* The mismatched data types forces the caller to deal with
+ * bad dc_type'd dc_data values, and makes it more convenient
+ * for the caller to not have to do the grunge work of setting
+ * up a dc_type result.
+ */
+dc_data
+dc_dup_num DC_DECLARG((value))
+       dc_num value DC_DECLEND
+{
+       dc_data result;
+
+       ++CastNum(value)->n_refs;
+       result.v.number = value;
+       result.dc_type = DC_NUMBER;
+       return result;
+}
+
+\f
+
+/*---------------------------------------------------------------------------\
+| The rest of this file consists of stubs for bc routines called by numeric.c|
+| so as to minimize the amount of bc code needed to build dc.                |
+| The bulk of the code was just lifted straight out of the bc source.        |
+\---------------------------------------------------------------------------*/
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_STDARG_H
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+
+int out_col = 0;
+
+/* Output routines: Write a character CH to the standard output.
+   It keeps track of the number of characters output and may
+   break the output with a "\<cr>". */
+
+static void
+out_char (ch)
+     int ch;
+{
+
+  if (ch == '\0')
+    {
+      out_col = 0;
+    }
+  else
+    {
+      out_col++;
+      if (out_col == 70)
+       {
+         putchar ('\\');
+         putchar ('\n');
+         out_col = 1;
+       }
+      putchar (ch);
+    }
+}
+
+/* Malloc could not get enough memory. */
+
+void
+out_of_memory()
+{
+  dc_memfail();
+}
+
+/* Runtime error will  print a message and stop the machine. */
+
+#ifdef HAVE_STDARG_H
+#ifdef __STDC__
+void
+rt_error (char *mesg, ...)
+#else
+void
+rt_error (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_error (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+
+  fprintf (stderr, "Runtime error: ");
+#ifdef HAVE_STDARG_H
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vfprintf (stderr, mesg, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+}
+
+
+/* A runtime warning tells of some action taken by the processor that
+   may change the program execution but was not enough of a problem
+   to stop the execution. */
+
+#ifdef HAVE_STDARG_H
+#ifdef __STDC__
+void
+rt_warn (char *mesg, ...)
+#else
+void
+rt_warn (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_warn (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+
+  fprintf (stderr, "Runtime warning: ");
+#ifdef HAVE_STDARG_H
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vfprintf (stderr, mesg, args);
+  va_end (args);
+  fprintf (stderr, "\n");
+}
diff --git a/dc/stack.c b/dc/stack.c
new file mode 100644 (file)
index 0000000..1d8a9bf
--- /dev/null
@@ -0,0 +1,494 @@
+/* 
+ * implement stack functions for dc
+ *
+ * Copyright (C) 1994, 1997, 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, you can either send email to this
+ * program's author (see below) or write to:
+ *
+ *    The Free Software Foundation, Inc.
+ *    59 Temple Place, Suite 330
+ *    Boston, MA 02111 USA
+ */
+
+/* This module is the only one that knows what stacks (both the
+ * regular evaluation stack and the named register stacks)
+ * look like.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#include "dc.h"
+#include "dc-proto.h"
+#include "dc-regdef.h"
+
+/* an oft-used error message: */
+#define Empty_Stack    fprintf(stderr, "%s: stack empty\n", progname)
+
+
+/* simple linked-list implementaion suffices: */
+struct dc_list {
+       dc_data value;
+       struct dc_array *array; /* opaque */
+       struct dc_list *link;
+};
+typedef struct dc_list dc_list;
+
+/* the anonymous evaluation stack */
+static dc_list *dc_stack=NULL;
+
+/* the named register stacks */
+static dc_list *dc_register[DC_REGCOUNT];
+
+\f
+/* allocate a new dc_list item */
+static dc_list *
+dc_alloc DC_DECLVOID()
+{
+       dc_list *result;
+
+       result = dc_malloc(sizeof *result);
+       result->value.dc_type = DC_UNINITIALIZED;
+       result->array = NULL;
+       result->link = NULL;
+       return result;
+}
+
+\f
+/* check that there are two numbers on top of the stack,
+ * then call op with the popped numbers.  Construct a dc_data
+ * value from the dc_num returned by op and push it
+ * on the stack.
+ * If the op call doesn't return DC_SUCCESS, then leave the stack
+ * unmodified.
+ */
+void
+dc_binop DC_DECLARG((op, kscale))
+       int (*op)DC_PROTO((dc_num, dc_num, int, dc_num *)) DC_DECLSEP
+       int kscale DC_DECLEND
+{
+       dc_data a;
+       dc_data b;
+       dc_data r;
+
+       if (!dc_stack || !dc_stack->link){
+               Empty_Stack;
+               return;
+       }
+       if (dc_stack->value.dc_type!=DC_NUMBER
+                       || dc_stack->link->value.dc_type!=DC_NUMBER){
+               fprintf(stderr, "%s: non-numeric value\n", progname);
+               return;
+       }
+       (void)dc_pop(&b);
+       (void)dc_pop(&a);
+       if ((*op)(a.v.number, b.v.number, kscale, &r.v.number) == DC_SUCCESS){
+               r.dc_type = DC_NUMBER;
+               dc_push(r);
+               dc_free_num(&a.v.number);
+               dc_free_num(&b.v.number);
+       }else{
+               /* op failed; restore the stack */
+               dc_push(a);
+               dc_push(b);
+       }
+}
+
+/* check that there are two numbers on top of the stack,
+ * then call op with the popped numbers.  Construct two dc_data
+ * values from the dc_num's returned by op and push them
+ * on the stack.
+ * If the op call doesn't return DC_SUCCESS, then leave the stack
+ * unmodified.
+ */
+void
+dc_binop2 DC_DECLARG((op, kscale))
+       int (*op)DC_PROTO((dc_num, dc_num, int, dc_num *, dc_num *)) DC_DECLSEP
+       int kscale DC_DECLEND
+{
+       dc_data a;
+       dc_data b;
+       dc_data r1;
+       dc_data r2;
+
+       if (!dc_stack || !dc_stack->link){
+               Empty_Stack;
+               return;
+       }
+       if (dc_stack->value.dc_type!=DC_NUMBER
+                       || dc_stack->link->value.dc_type!=DC_NUMBER){
+               fprintf(stderr, "%s: non-numeric value\n", progname);
+               return;
+       }
+       (void)dc_pop(&b);
+       (void)dc_pop(&a);
+       if ((*op)(a.v.number, b.v.number, kscale,
+                                                               &r1.v.number, &r2.v.number) == DC_SUCCESS){
+               r1.dc_type = DC_NUMBER;
+               dc_push(r1);
+               r2.dc_type = DC_NUMBER;
+               dc_push(r2);
+               dc_free_num(&a.v.number);
+               dc_free_num(&b.v.number);
+       }else{
+               /* op failed; restore the stack */
+               dc_push(a);
+               dc_push(b);
+       }
+}
+
+/* check that there are two numbers on top of the stack,
+ * then call dc_compare with the popped numbers.
+ * Return negative, zero, or positive based on the ordering
+ * of the two numbers.
+ */
+int
+dc_cmpop DC_DECLVOID()
+{
+       int result;
+       dc_data a;
+       dc_data b;
+
+       if (!dc_stack || !dc_stack->link){
+               Empty_Stack;
+               return 0;
+       }
+       if (dc_stack->value.dc_type!=DC_NUMBER
+                       || dc_stack->link->value.dc_type!=DC_NUMBER){
+               fprintf(stderr, "%s: non-numeric value\n", progname);
+               return 0;
+       }
+       (void)dc_pop(&b);
+       (void)dc_pop(&a);
+       result = dc_compare(b.v.number, a.v.number);
+       dc_free_num(&a.v.number);
+       dc_free_num(&b.v.number);
+       return result;
+}
+
+/* check that there are three numbers on top of the stack,
+ * then call op with the popped numbers.  Construct a dc_data
+ * value from the dc_num returned by op and push it
+ * on the stack.
+ * If the op call doesn't return DC_SUCCESS, then leave the stack
+ * unmodified.
+ */
+void
+dc_triop DC_DECLARG((op, kscale))
+       int (*op)DC_PROTO((dc_num, dc_num, dc_num, int, dc_num *)) DC_DECLSEP
+       int kscale DC_DECLEND
+{
+       dc_data a;
+       dc_data b;
+       dc_data c;
+       dc_data r;
+
+       if (!dc_stack || !dc_stack->link || !dc_stack->link->link){
+               Empty_Stack;
+               return;
+       }
+       if (dc_stack->value.dc_type!=DC_NUMBER
+                       || dc_stack->link->value.dc_type!=DC_NUMBER
+                       || dc_stack->link->link->value.dc_type!=DC_NUMBER){
+               fprintf(stderr, "%s: non-numeric value\n", progname);
+               return;
+       }
+       (void)dc_pop(&c);
+       (void)dc_pop(&b);
+       (void)dc_pop(&a);
+       if ((*op)(a.v.number, b.v.number, c.v.number,
+                               kscale, &r.v.number) == DC_SUCCESS){
+               r.dc_type = DC_NUMBER;
+               dc_push(r);
+               dc_free_num(&a.v.number);
+               dc_free_num(&b.v.number);
+               dc_free_num(&c.v.number);
+       }else{
+               /* op failed; restore the stack */
+               dc_push(a);
+               dc_push(b);
+               dc_push(c);
+       }
+}
+
+\f
+/* initialize the register stacks to their initial values */
+void
+dc_register_init DC_DECLVOID()
+{
+       int i;
+
+       for (i=0; i<DC_REGCOUNT; ++i)
+               dc_register[i] = NULL;
+}
+
+/* clear the evaluation stack */
+void
+dc_clear_stack DC_DECLVOID()
+{
+       dc_list *n;
+       dc_list *t;
+
+       for (n=dc_stack; n; n=t){
+               t = n->link;
+               if (n->value.dc_type == DC_NUMBER)
+                       dc_free_num(&n->value.v.number);
+               else if (n->value.dc_type == DC_STRING)
+                       dc_free_str(&n->value.v.string);
+               else
+                       dc_garbage("in stack", -1);
+               dc_array_free(n->array);
+               free(n);
+       }
+       dc_stack = NULL;
+}
+
+/* push a value onto the evaluation stack */
+void
+dc_push DC_DECLARG((value))
+       dc_data value DC_DECLEND
+{
+       dc_list *n = dc_alloc();
+
+       if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING)
+               dc_garbage("in data being pushed", -1);
+       n->value = value;
+       n->link = dc_stack;
+       dc_stack = n;
+}
+
+/* push a value onto the named register stack */
+void
+dc_register_push DC_DECLARG((stackid, value))
+       int stackid DC_DECLSEP
+       dc_data value DC_DECLEND
+{
+       dc_list *n = dc_alloc();
+
+       stackid = regmap(stackid);
+       n->value = value;
+       n->link = dc_register[stackid];
+       dc_register[stackid] = n;
+}
+
+/* set *result to the value on the top of the evaluation stack */
+/* The caller is responsible for duplicating the value if it
+ * is to be maintained as anything more than a transient identity.
+ *
+ * DC_FAIL is returned if the stack is empty (and *result unchanged),
+ * DC_SUCCESS is returned otherwise
+ */
+int
+dc_top_of_stack DC_DECLARG((result))
+       dc_data *result DC_DECLEND
+{
+       if (!dc_stack){
+               Empty_Stack;
+               return DC_FAIL;
+       }
+       if (dc_stack->value.dc_type!=DC_NUMBER
+                       && dc_stack->value.dc_type!=DC_STRING)
+               dc_garbage("at top of stack", -1);
+       *result = dc_stack->value;
+       return DC_SUCCESS;
+}
+
+/* set *result to a dup of the value on the top of the named register stack */
+/*
+ * DC_FAIL is returned if the named stack is empty (and *result unchanged),
+ * DC_SUCCESS is returned otherwise
+ */
+int
+dc_register_get DC_DECLARG((regid, result))
+       int regid DC_DECLSEP
+       dc_data *result DC_DECLEND
+{
+       dc_list *r;
+
+       regid = regmap(regid);
+       r = dc_register[regid];
+       if ( ! r ){
+               fprintf(stderr, "%s: register ", progname);
+               dc_show_id(stderr, regid, " is empty\n");
+               return DC_FAIL;
+       }
+       *result = dc_dup(r->value);
+       return DC_SUCCESS;
+}
+
+/* set the top of the named register stack to the indicated value */
+/* If the named stack is empty, craft a stack entry to enter the
+ * value into.
+ */
+void
+dc_register_set DC_DECLARG((regid, value))
+       int regid DC_DECLSEP
+       dc_data value DC_DECLEND
+{
+       dc_list *r;
+
+       regid = regmap(regid);
+       r = dc_register[regid];
+       if ( ! r )
+               dc_register[regid] = dc_alloc();
+       else if (r->value.dc_type == DC_NUMBER)
+               dc_free_num(&r->value.v.number);
+       else if (r->value.dc_type == DC_STRING)
+               dc_free_str(&r->value.v.string);
+       else if (r->value.dc_type == DC_UNINITIALIZED)
+               ;
+       else
+               dc_garbage("", regid);
+       dc_register[regid]->value = value;
+}
+
+/* pop from the evaluation stack
+ *
+ * DC_FAIL is returned if the stack is empty (and *result unchanged),
+ * DC_SUCCESS is returned otherwise
+ */
+int
+dc_pop DC_DECLARG((result))
+       dc_data *result DC_DECLEND
+{
+       dc_list *r;
+
+       r = dc_stack;
+       if (!r){
+               Empty_Stack;
+               return DC_FAIL;
+       }
+       if (r->value.dc_type!=DC_NUMBER && r->value.dc_type!=DC_STRING)
+               dc_garbage("at top of stack", -1);
+       *result = r->value;
+       dc_stack = r->link;
+       dc_array_free(r->array);
+       free(r);
+       return DC_SUCCESS;
+}
+
+/* pop from the named register stack
+ *
+ * DC_FAIL is returned if the named stack is empty (and *result unchanged),
+ * DC_SUCCESS is returned otherwise
+ */
+int
+dc_register_pop DC_DECLARG((stackid, result))
+       int stackid DC_DECLSEP
+       dc_data *result DC_DECLEND
+{
+       dc_list *r;
+
+       stackid = regmap(stackid);
+       r = dc_register[stackid];
+       if (!r){
+               fprintf(stderr, "%s: stack register ", progname);
+               dc_show_id(stderr, stackid, " is empty\n");
+               return DC_FAIL;
+       }
+       if (r->value.dc_type!=DC_NUMBER && r->value.dc_type!=DC_STRING)
+               dc_garbage(" stack", stackid);
+       *result = r->value;
+       dc_register[stackid] = r->link;
+       dc_array_free(r->array);
+       free(r);
+       return DC_SUCCESS;
+}
+
+\f
+/* tell how many entries are currently on the evaluation stack */
+int
+dc_tell_stackdepth DC_DECLVOID()
+{
+       dc_list *n;
+       int depth=0;
+
+       for (n=dc_stack; n; n=n->link)
+               ++depth;
+       return depth;
+}
+
+
+/* return the length of the indicated data value;
+ * if discard_p is DC_TOSS, the deallocate the value when done
+ *
+ * The definition of a datum's length is deligated to the
+ * appropriate module.
+ */
+int
+dc_tell_length DC_DECLARG((value, discard_p))
+       dc_data value DC_DECLSEP
+       dc_discard discard_p DC_DECLEND
+{
+       int length;
+
+       if (value.dc_type == DC_NUMBER){
+               length = dc_numlen(value.v.number);
+               if (discard_p == DC_TOSS)
+                       dc_free_num(&value.v.number);
+       } else if (value.dc_type == DC_STRING) {
+               length = dc_strlen(value.v.string);
+               if (discard_p == DC_TOSS)
+                       dc_free_str(&value.v.string);
+       } else {
+               dc_garbage("in tell_length", -1);
+               /*NOTREACHED*/
+               length = 0;     /*just to suppress spurious compiler warnings*/
+       }
+       return length;
+}
+
+\f
+
+/* print out all of the values on the evaluation stack */
+void
+dc_printall DC_DECLARG((obase))
+       int obase DC_DECLEND
+{
+       dc_list *n;
+
+       for (n=dc_stack; n; n=n->link)
+               dc_print(n->value, obase, DC_WITHNL, DC_KEEP);
+}
+
+\f
+
+
+/* get the current array head for the named array */
+struct dc_array *
+dc_get_stacked_array DC_DECLARG((array_id))
+       int array_id DC_DECLEND
+{
+       dc_list *r = dc_register[regmap(array_id)];
+       return r ? r->array : NULL;
+}
+
+/* set the current array head for the named array */
+void
+dc_set_stacked_array DC_DECLARG((array_id, new_head))
+       int array_id DC_DECLSEP
+       struct dc_array *new_head DC_DECLEND
+{
+       dc_list *r;
+
+       array_id = regmap(array_id);
+       r = dc_register[array_id];
+       if ( ! r )
+               r = dc_register[array_id] = dc_alloc();
+       r->array = new_head;
+}
diff --git a/dc/string.c b/dc/string.c
new file mode 100644 (file)
index 0000000..a7f79a4
--- /dev/null
@@ -0,0 +1,211 @@
+/* 
+ * implement string functions for dc
+ *
+ * Copyright (C) 1994, 1997, 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, you can either send email to this
+ * program's author (see below) or write to:
+ *
+ *    The Free Software Foundation, Inc.
+ *    59 Temple Place, Suite 330
+ *    Boston, MA 02111 USA
+ */
+
+/* This should be the only module that knows the internals of type dc_string */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>   /* ptrdiff_t */
+#else
+# define ptrdiff_t     size_t
+#endif
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>   /* memcpy */
+#else
+# ifdef HAVE_MEMORY_H
+#  include <memory.h>  /* memcpy, maybe */
+# else
+#  ifdef HAVE_STRINGS_H
+#   include <strings.h>        /* memcpy, maybe */
+#  endif
+# endif
+#endif
+#include "dc.h"
+#include "dc-proto.h"
+
+/* here is the completion of the dc_string type: */
+struct dc_string {
+       char *s_ptr;  /* pointer to base of string */
+       size_t s_len; /* length of counted string */
+       int  s_refs;  /* reference count to cut down on memory use by duplicates */
+};
+
+\f
+/* return a duplicate of the string in the passed value */
+/* The mismatched data types forces the caller to deal with
+ * bad dc_type'd dc_data values, and makes it more convenient
+ * for the caller to not have to do the grunge work of setting
+ * up a dc_type result.
+ */
+dc_data
+dc_dup_str DC_DECLARG((value))
+       dc_str value DC_DECLEND
+{
+       dc_data result;
+
+       ++value->s_refs;
+       result.v.string = value;
+       result.dc_type = DC_STRING;
+       return result;
+}
+
+/* free an instance of a dc_str value */
+void
+dc_free_str DC_DECLARG((value))
+       dc_str *value DC_DECLEND
+{
+       struct dc_string *string = *value;
+
+       if (--string->s_refs < 1){
+               free(string->s_ptr);
+               free(string);
+       }
+}
+
+/* Output a dc_str value.
+ * Add a trailing newline if "newline" is set.
+ * Free the value after use if discard_flag is set.
+ */
+void
+dc_out_str DC_DECLARG((value, newline, discard_flag))
+       dc_str value DC_DECLSEP
+       dc_newline newline DC_DECLSEP
+       dc_discard discard_flag DC_DECLEND
+{
+       fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
+       if (newline == DC_WITHNL)
+               putchar('\n');
+       if (discard_flag == DC_TOSS)
+               dc_free_str(&value);
+}
+
+/* make a copy of a string (base s, length len)
+ * into a dc_str value; return a dc_data result
+ * with this value
+ */
+dc_data
+dc_makestring DC_DECLARG((s, len))
+       const char *s DC_DECLSEP
+       size_t len DC_DECLEND
+{
+       dc_data result;
+       struct dc_string *string;
+
+       string = dc_malloc(sizeof *string);
+       string->s_ptr = dc_malloc(len+1);
+       memcpy(string->s_ptr, s, len);
+       string->s_ptr[len] = '\0';      /* nul terminated for those who need it */
+       string->s_len = len;
+       string->s_refs = 1;
+       result.v.string = string;
+       result.dc_type = DC_STRING;
+       return result;
+}
+
+/* read a dc_str value from FILE *fp;
+ * if ldelim == rdelim, then read until a ldelim char or EOF is reached;
+ * if ldelim != rdelim, then read until a matching rdelim for the
+ * (already eaten) first ldelim is read.
+ * Return a dc_data result with the dc_str value as its contents.
+ */
+dc_data
+dc_readstring DC_DECLARG((fp, ldelim, rdelim))
+       FILE *fp DC_DECLSEP
+       int ldelim DC_DECLSEP
+       int rdelim DC_DECLEND
+{
+       static char *line_buf = NULL;   /* a buffer to build the string in */ 
+       static size_t buflen = 0;               /* the current size of line_buf */
+       int depth=1;
+       int c;
+       char *p;
+       const char *end;
+
+       if (!line_buf){
+               /* initial buflen should be large enough to handle most cases */
+               buflen = 2016;
+               line_buf = dc_malloc(buflen);
+       }
+       p = line_buf;
+       end = line_buf + buflen;
+       for (;;){
+               c = getc(fp);
+               if (c == EOF)
+                       break;
+               else if (c == rdelim && --depth < 1)
+                       break;
+               else if (c == ldelim)
+                       ++depth;
+               if (p >= end){
+                       ptrdiff_t offset = p - line_buf;
+                       /* buflen increment should be big enough
+                        * to avoid execessive reallocs:
+                        */
+                       buflen += 2048;
+                       line_buf = realloc(line_buf, buflen);
+                       if (!line_buf)
+                               dc_memfail();
+                       p = line_buf + offset;
+                       end = line_buf + buflen;
+               }
+               *p++ = c;
+       }
+       return dc_makestring(line_buf, (size_t)(p-line_buf));
+}
+
+/* return the base pointer of the dc_str value;
+ * This function is needed because no one else knows what dc_str
+ * looks like.
+ */
+const char *
+dc_str2charp DC_DECLARG((value))
+       dc_str value DC_DECLEND
+{
+       return value->s_ptr;
+}
+
+/* return the length of the dc_str value;
+ * This function is needed because no one else knows what dc_str
+ * looks like, and strlen(dc_str2charp(value)) won't work
+ * if there's an embedded '\0'.
+ */
+size_t
+dc_strlen DC_DECLARG((value))
+       dc_str value DC_DECLEND
+{
+       return value->s_len;
+}
+
+\f
+/* initialize the strings subsystem */
+void
+dc_string_init DC_DECLVOID()
+{
+       /* nothing to do for this implementation */
+}
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644 (file)
index 0000000..a729cee
--- /dev/null
@@ -0,0 +1,12 @@
+## Process this file with automake to produce Makefile.in
+
+info_TEXINFOS = bc.texi dc.texi
+MAKEINFO = makeinfo --no-split
+
+MAINTAINERCLEANFILES = Makefile.in
+
+# FIXME: remove this when automake has been fixed to include these
+# files automatically
+EXTRA_DIST = bc.1 dc.1
+
+man_MANS = bc.1 dc.1
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644 (file)
index 0000000..840d007
--- /dev/null
@@ -0,0 +1,355 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+LEX = @LEX@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+READLINELIB = @READLINELIB@
+VERSION = @VERSION@
+YACC = @YACC@
+
+info_TEXINFOS = bc.texi dc.texi
+MAKEINFO = makeinfo --no-split
+
+MAINTAINERCLEANFILES = Makefile.in
+
+# FIXME: remove this when automake has been fixed to include these
+# files automatically
+EXTRA_DIST = bc.1 dc.1
+
+man_MANS = bc.1 dc.1
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+TEXI2DVI = texi2dvi
+INFO_DEPS = bc.info dc.info
+DVIS = bc.dvi dc.dvi
+TEXINFOS = bc.texi dc.texi
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON =  Makefile.am Makefile.in texinfo.tex
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .dvi .info .ps .texi .texinfo .txi
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps doc/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+bc.info: bc.texi
+bc.dvi: bc.texi
+
+
+dc.info: dc.texi
+dc.dvi: dc.texi
+
+
+DVIPS = dvips
+
+.texi.info:
+       @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       cd $(srcdir) \
+         && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+.texi.dvi:
+       TEXINPUTS=.:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.texi:
+       @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       cd $(srcdir) \
+         && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+.texinfo.info:
+       @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       cd $(srcdir) \
+         && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+.texinfo:
+       @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       cd $(srcdir) \
+         && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+.texinfo.dvi:
+       TEXINPUTS=.:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi.info:
+       @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       cd $(srcdir) \
+         && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+
+.txi.dvi:
+       TEXINPUTS=.:$$TEXINPUTS \
+         MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
+
+.txi:
+       @cd $(srcdir) && rm -f $@ $@-[0-9] $@-[0-9][0-9]
+       cd $(srcdir) \
+         && $(MAKEINFO) `echo $< | sed 's,.*/,,'`
+.dvi.ps:
+       $(DVIPS) $< -o $@
+
+install-info-am: $(INFO_DEPS)
+       @$(NORMAL_INSTALL)
+       $(mkinstalldirs) $(DESTDIR)$(infodir)
+       @list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         d=$(srcdir); \
+         for ifile in `cd $$d && echo $$file $$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 \
+         list='$(INFO_DEPS)'; \
+         for file in $$list; 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; \
+       list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         test -z "$ii" \
+           || install-info --info-dir=$(DESTDIR)$(infodir) --remove $$file; \
+       done
+       @$(NORMAL_UNINSTALL)
+       list='$(INFO_DEPS)'; \
+       for file in $$list; do \
+         (cd $(DESTDIR)$(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \
+       done
+
+dist-info: $(INFO_DEPS)
+       list='$(INFO_DEPS)'; \
+       for base in $$list; 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 bc.aux bc.cp bc.cps bc.dvi bc.fn bc.fns bc.ky bc.kys bc.ps \
+         bc.log bc.pg bc.toc bc.tp bc.tps bc.vr bc.vrs bc.op bc.tr \
+         bc.cv bc.cn dc.aux dc.cp dc.cps dc.dvi dc.fn dc.fns dc.ky \
+         dc.kys dc.ps dc.log dc.pg dc.toc dc.tp dc.tps dc.vr dc.vrs \
+         dc.op dc.tr dc.cv dc.cn
+
+clean-aminfo:
+
+distclean-aminfo:
+
+maintainer-clean-aminfo:
+       cd $(srcdir) && for i in $(INFO_DEPS); do \
+         rm -f $$i; \
+         if test "`echo $$i-[0-9]*`" != "$$i-[0-9]*"; then \
+           rm -f $$i-[0-9]*; \
+         fi; \
+       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) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+       @$(NORMAL_UNINSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = doc
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+       $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
+info-am: $(INFO_DEPS)
+info: info-am
+dvi-am: $(DVIS)
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-info-am install-man
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-info uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(INFO_DEPS) $(MANS)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+       $(mkinstalldirs)  $(DESTDIR)$(infodir) $(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+mostlyclean-am:  mostlyclean-aminfo mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-aminfo clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-aminfo distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-aminfo maintainer-clean-generic \
+               distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: install-info-am uninstall-info mostlyclean-aminfo \
+distclean-aminfo clean-aminfo maintainer-clean-aminfo install-man1 \
+uninstall-man1 install-man uninstall-man tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# 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:
diff --git a/doc/bc.1 b/doc/bc.1
new file mode 100644 (file)
index 0000000..c0b03f7
--- /dev/null
+++ b/doc/bc.1
@@ -0,0 +1,792 @@
+.\"
+.\" bc.1 - the *roff document processor source for the bc manual
+.\"
+.\" This file is part of GNU bc.
+.\" Copyright (C) 1991-1994, 1997, 2000 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 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; see the file COPYING.  If not, write to:
+.\"   The Free Software Foundation, Inc.
+.\"   59 Temple Place, Suite 330
+.\"   Boston, MA 02111 USA
+.\"
+.\" You may contact the author by:
+.\" e-mail: philnelson@acm.org
+.\" us-mail: Philip A. Nelson
+.\" Computer Science Department, 9062
+.\" Western Washington University
+.\" Bellingham, WA 98226-9062
+.\"
+.\"
+.TH bc 1 .\" "Command Manual" v1.06 "Sept 12, 2000"
+.SH NAME
+bc - An arbitrary precision calculator language
+.SH SYNTAX
+\fBbc\fR [ \fB-hlwsqv\fR ] [long-options] [ \fI file ...\fR ]
+.SH VERSION
+This man page documents GNU bc version 1.06.
+.SH DESCRIPTION
+\fBbc\fR is a language that supports arbitrary precision numbers
+with interactive execution of statements.  There are some similarities
+in the syntax to the C programming language. 
+A standard math library is available by command line option.
+If requested, the math library is defined before processing any files.
+\fBbc\fR starts by processing code from all the files listed
+on the command line in the order listed.  After all files have been
+processed, \fBbc\fR reads from the standard input.  All code is
+executed as it is read.  (If a file contains a command to halt the
+processor, \fBbc\fR will never read from the standard input.)
+.PP
+This version of \fBbc\fR contains several extensions beyond
+traditional \fBbc\fR implementations and the POSIX draft standard.
+Command line options can cause these extensions to print a warning 
+or to be rejected.  This 
+document describes the language accepted by this processor.
+Extensions will be identified as such.
+.SS OPTIONS
+.IP "-h, --help"
+Print the usage and exit.
+.IP "-i, --interactive"
+Force interactive mode.
+.IP "-l, --mathlib"
+Define the standard math library.
+.IP "-w, --warn"
+Give warnings for extensions to POSIX \fBbc\fR.
+.IP "-s, --standard"
+Process exactly the POSIX \fBbc\fR language.
+.IP "-q, --quiet"
+Do not print the normal GNU bc welcome.
+.IP "-v, --version"
+Print the version number and copyright and quit.
+.SS NUMBERS
+The most basic element in \fBbc\fR is the number.  Numbers are
+arbitrary precision numbers.  This precision is both in the integer
+part and the fractional part.  All numbers are represented internally
+in decimal and all computation is done in decimal.  (This version
+truncates results from divide and multiply operations.)  There are two
+attributes of numbers, the length and the scale.  The length is the
+total number of significant decimal digits in a number and the scale
+is the total number of decimal digits after the decimal point.  For
+example:
+.nf
+.RS
+ .000001 has a length of 6 and scale of 6.
+ 1935.000 has a length of 7 and a scale of 3.
+.RE
+.fi
+.SS VARIABLES
+Numbers are stored in two types of variables, simple variables and
+arrays.  Both simple variables and array variables are named.  Names
+begin with a letter followed by any number of letters, digits and
+underscores.  All letters must be lower case.  (Full alpha-numeric
+names are an extension. In POSIX \fBbc\fR all names are a single
+lower case letter.)  The type of variable is clear by the context
+because all array variable names will be followed by brackets ([]).
+.PP
+There are four special variables, \fBscale, ibase, obase,\fR and
+\fBlast\fR.  \fBscale\fR defines how some operations use digits after the
+decimal point.  The default value of \fBscale\fR is 0. \fBibase\fR
+and \fBobase\fR define the conversion base for input and output
+numbers.  The default for both input and output is base 10.
+\fBlast\fR (an extension) is a variable that has the value of the last
+printed number.  These will be discussed in further detail where
+appropriate.  All of these variables may have values assigned to them
+as well as used in expressions.
+.SS COMMENTS
+Comments in \fBbc\fR start with the characters \fB/*\fR and end with
+the characters \fB*/\fR.  Comments may start anywhere and appear as a
+single space in the input.  (This causes comments to delimit other
+input items.  For example, a comment can not be found in the middle of
+a variable name.)  Comments include any newlines (end of line) between
+the start and the end of the comment.
+.PP
+To support the use of scripts for \fBbc\fR, a single line comment has been
+added as an extension.  A single line comment starts at a \fB#\fR
+character and continues to the next end of the line.  The end of line
+character is not part of the comment and is processed normally.
+.SS EXPRESSIONS
+The numbers are manipulated by expressions and statements.  Since
+the language was designed to be interactive, statements and expressions
+are executed as soon as possible.  There is no "main" program.  Instead,
+code is executed as it is encountered.  (Functions, discussed in
+detail later, are defined when encountered.)
+.PP
+A simple expression is just a constant. \fBbc\fR converts constants
+into internal decimal numbers using the current input base, specified
+by the variable \fBibase\fR. (There is an exception in functions.)
+The legal values of \fBibase\fR are 2 through 16.  Assigning a
+value outside this range to \fBibase\fR will result in a value of 2
+or 16.  Input numbers may contain the characters 0-9 and A-F. (Note:
+They must be capitals.  Lower case letters are variable names.)
+Single digit numbers always have the value of the digit regardless of
+the value of \fBibase\fR. (i.e. A = 10.)  For multi-digit numbers,
+\fBbc\fR changes all input digits greater or equal to ibase to the
+value of \fBibase\fR-1.  This makes the number \fBFFF\fR always be
+the largest 3 digit number of the input base.
+.PP
+Full expressions are similar to many other high level languages.
+Since there is only one kind of number, there are no rules for mixing
+types.  Instead, there are rules on the scale of expressions.  Every
+expression has a scale.  This is derived from the scale of original
+numbers, the operation performed and in many cases, the value of the
+variable \fBscale\fR. Legal values of the variable \fBscale\fR are
+0 to the maximum number representable by a C integer.
+.PP
+In the following descriptions of legal expressions, "expr" refers to a
+complete expression and "var" refers to a simple or an array variable.
+A simple variable is just a
+.RS
+\fIname\fR
+.RE
+and an array variable is specified as
+.RS
+\fIname\fR[\fIexpr\fR]
+.RE
+Unless specifically
+mentioned the scale of the result is the maximum scale of the
+expressions involved.
+.IP "- expr"
+The result is the negation of the expression.
+.IP "++ var"
+The variable is incremented by one and the new value is the result of
+the expression.
+.IP "-- var"
+The variable
+is decremented by one and the new value is the result of the
+expression.
+.IP "var ++"
+ The result of the expression is the value of
+the variable and then the variable is incremented by one.
+.IP "var --"
+The result of the expression is the value of the variable and then
+the variable is decremented by one.
+.IP "expr + expr"
+The result of the expression is the sum of the two expressions.
+.IP "expr - expr"
+The result of the expression is the difference of the two expressions.
+.IP "expr * expr"
+The result of the expression is the product of the two expressions.
+.IP "expr / expr"
+The result of the expression is the quotient of the two expressions.
+The scale of the result is the value of the variable \fBscale\fR.
+.IP "expr % expr"
+The result of the expression is the "remainder" and it is computed in the
+following way.  To compute a%b, first a/b is computed to \fBscale\fR
+digits.  That result is used to compute a-(a/b)*b to the scale of the
+maximum of \fBscale\fR+scale(b) and scale(a).  If \fBscale\fR is set
+to zero and both expressions are integers this expression is the
+integer remainder function.
+.IP "expr ^ expr"
+The result of the expression is the value of the first raised to the
+second. The second expression must be an integer.  (If the second
+expression is not an integer, a warning is generated and the
+expression is truncated to get an integer value.)  The scale of the
+result is \fBscale\fR if the exponent is negative.  If the exponent
+is positive the scale of the result is the minimum of the scale of the
+first expression times the value of the exponent and the maximum of
+\fBscale\fR and the scale of the first expression.  (e.g. scale(a^b)
+= min(scale(a)*b, max( \fBscale,\fR scale(a))).)  It should be noted
+that expr^0 will always return the value of 1.
+.IP "( expr )"
+This alters the standard precedence to force the evaluation of the
+expression.
+.IP "var = expr"
+The variable is assigned the value of the expression.
+.IP "var <op>= expr"
+This is equivalent to "var = var <op> expr" with the exception that
+the "var" part is evaluated only once.  This can make a difference if
+"var" is an array.
+.PP
+ Relational expressions are a special kind of expression
+that always evaluate to 0 or 1, 0 if the relation is false and 1 if
+the relation is true.  These may appear in any legal expression.
+(POSIX bc requires that relational expressions are used only in if,
+while, and for statements and that only one relational test may be
+done in them.)  The relational operators are
+.IP "expr1 < expr2"
+The result is 1 if expr1 is strictly less than expr2.
+.IP "expr1 <= expr2"
+The result is 1 if expr1 is less than or equal to expr2.
+.IP "expr1 > expr2"
+The result is 1 if expr1 is strictly greater than expr2.
+.IP "expr1 >= expr2"
+The result is 1 if expr1 is greater than or equal to expr2.
+.IP "expr1 == expr2"
+The result is 1 if expr1 is equal to expr2.
+.IP "expr1 != expr2"
+The result is 1 if expr1 is not equal to expr2.
+.PP
+Boolean operations are also legal.  (POSIX \fBbc\fR does NOT have
+boolean operations). The result of all boolean operations are 0 and 1
+(for false and true) as in relational expressions.  The boolean
+operators are:
+.IP "!expr"
+The result is 1 if expr is 0.
+.IP "expr && expr"
+The result is 1 if both expressions are non-zero.
+.IP "expr || expr"
+The result is 1 if either expression is non-zero.
+.PP
+The expression precedence is as follows: (lowest to highest)
+.nf
+.RS
+|| operator, left associative
+&& operator, left associative
+! operator, nonassociative
+Relational operators, left associative
+Assignment operator, right associative
++ and - operators, left associative
+*, / and % operators, left associative
+^ operator, right associative
+unary - operator, nonassociative
+++ and -- operators, nonassociative
+.RE
+.fi
+.PP
+This precedence was chosen so that POSIX compliant \fBbc\fR programs
+will run correctly. This will cause the use of the relational and
+logical operators to have some unusual behavior when used with
+assignment expressions.  Consider the expression:
+.RS
+a = 3 < 5
+.RE
+.PP
+Most C programmers would assume this would assign the result of "3 <
+5" (the value 1) to the variable "a".  What this does in \fBbc\fR is
+assign the value 3 to the variable "a" and then compare 3 to 5.  It is
+best to use parenthesis when using relational and logical operators
+with the assignment operators.
+.PP
+There are a few more special expressions that are provided in \fBbc\fR.
+These have to do with user defined functions and standard
+functions.  They all appear as "\fIname\fB(\fIparameters\fB)\fR".
+See the section on functions for user defined functions.  The standard
+functions are:
+.IP "length ( expression )"
+The value of the length function is the number of significant digits in the
+expression.
+.IP "read ( )"
+The read function (an extension) will read a number from the standard
+input, regardless of where the function occurs.   Beware, this can
+cause problems with the mixing of data and program in the standard input.
+The best use for this function is in a previously written program that
+needs input from the user, but never allows program code to be input
+from the user.  The value of the read function is the number read from
+the standard input using the current value of the variable 
+\fBibase\fR for the conversion base.
+.IP "scale ( expression )"
+The value of the scale function is the number of digits after the decimal
+point in the expression.
+.IP "sqrt ( expression )"
+The value of the sqrt function is the square root of the expression.  If
+the expression is negative, a run time error is generated.
+.SS STATEMENTS
+Statements (as in most algebraic languages) provide the sequencing of
+expression evaluation.  In \fBbc\fR statements are executed "as soon
+as possible."  Execution happens when a newline in encountered and
+there is one or more complete statements.  Due to this immediate
+execution, newlines are very important in \fBbc\fR. In fact, both a
+semicolon and a newline are used as statement separators.  An
+improperly placed newline will cause a syntax error.  Because newlines
+are statement separators, it is possible to hide a newline by using
+the backslash character.  The sequence "\e<nl>", where <nl> is the
+newline appears to \fBbc\fR as whitespace instead of a newline.  A
+statement list is a series of statements separated by semicolons and
+newlines.  The following is a list of \fBbc\fR statements and what
+they do: (Things enclosed in brackets ([]) are optional parts of the
+statement.)
+.IP "expression"
+This statement does one of two things.  If the expression starts with
+"<variable> <assignment> ...", it is considered to be an assignment
+statement.  If the expression is not an assignment statement, the
+expression is evaluated and printed to the output.  After the number
+is printed, a newline is printed.  For example, "a=1" is an assignment
+statement and "(a=1)" is an expression that has an embedded
+assignment.  All numbers that are printed are printed in the base
+specified by the variable \fBobase\fR. The legal values for \fB
+obase\fR are 2 through BC_BASE_MAX.  (See the section LIMITS.)  For
+bases 2 through 16, the usual method of writing numbers is used.  For
+bases greater than 16, \fBbc\fR uses a multi-character digit method
+of printing the numbers where each higher base digit is printed as a
+base 10 number.  The multi-character digits are separated by spaces.
+Each digit contains the number of characters required to represent the
+base ten value of "obase-1".  Since numbers are of arbitrary
+precision, some numbers may not be printable on a single output line.
+These long numbers will be split across lines using the "\e" as the
+last character on a line.  The maximum number of characters printed
+per line is 70.  Due to the interactive nature of \fBbc\fR, printing
+a number causes the side effect of assigning the printed value to the
+special variable \fBlast\fR. This allows the user to recover the
+last value printed without having to retype the expression that
+printed the number.  Assigning to \fBlast\fR is legal and will
+overwrite the last printed value with the assigned value.  The newly
+assigned value will remain until the next number is printed or another
+value is assigned to \fBlast\fR.  (Some installations may allow the 
+use of a single period (.) which is not part of a number as a short
+hand notation for for \fBlast\fR.)
+.IP "string"
+The string is printed to the output.  Strings start with a double quote
+character and contain all characters until the next double quote character.
+All characters are take literally, including any newline.  No newline
+character is printed after the string.
+.IP "\fBprint\fR list"
+The print statement (an extension) provides another method of output.
+The "list" is a list of strings and expressions separated by commas.
+Each string or expression is printed in the order of the list.  No
+terminating newline is printed.  Expressions are evaluated and their
+value is printed and assigned to the variable \fBlast\fR. Strings
+in the print statement are printed to the output and may contain
+special characters.  Special characters start with the backslash
+character (\e).  The special characters recognized by \fBbc\fR are
+"a" (alert or bell), "b" (backspace), "f" (form feed), "n" (newline),
+"r" (carriage return), "q" (double quote), "t" (tab), and "\e" (backslash).
+Any other character following the backslash will be ignored.  
+.IP "{ statement_list }"
+This is the compound statement.  It allows multiple statements to be
+grouped together for execution.
+.IP "\fBif\fR ( expression ) statement1 [\fBelse\fR statement2]"
+The if statement evaluates the expression and executes statement1 or
+statement2 depending on the value of the expression.  If the expression
+is non-zero, statement1 is executed.  If statement2 is present and
+the value of the expression is 0, then statement2 is executed.  (The
+else clause is an extension.)
+.IP "\fBwhile\fR ( expression ) statement"
+The while statement will execute the statement while the expression
+is non-zero.  It evaluates the expression before each execution of
+the statement.   Termination of the loop is caused by a zero
+expression value or the execution of a break statement.
+.IP "\fBfor\fR ( [expression1] ; [expression2] ; [expression3] ) statement"
+The for statement controls repeated execution of the statement.  
+Expression1 is evaluated before the loop.  Expression2 is evaluated
+before each execution of the statement.  If it is non-zero, the statement
+is evaluated.  If it is zero, the loop is terminated.  After each
+execution of the statement, expression3 is evaluated before the reevaluation
+of expression2.  If expression1 or expression3 are missing, nothing is
+evaluated at the point they would be evaluated.
+If expression2 is missing, it is the same as substituting
+the value 1 for expression2.  (The optional expressions are an
+extension. POSIX \fBbc\fR requires all three expressions.)
+The following is equivalent code for the for statement:
+.nf
+.RS
+expression1;
+while (expression2) {
+   statement;
+   expression3;
+}
+.RE
+.fi
+.IP "\fBbreak\fR"
+This statement causes a forced exit of the most recent enclosing while
+statement or for statement.
+.IP "\fBcontinue\fR"
+The continue statement (an extension)  causes the most recent enclosing
+for statement to start the next iteration.
+.IP "\fBhalt\fR"
+The halt statement (an extension) is an executed statement that causes
+the \fBbc\fR processor to quit only when it is executed.  For example,
+"if (0 == 1) halt" will not cause \fBbc\fR to terminate because the halt is
+not executed.
+.IP "\fBreturn\fR"
+Return the value 0 from a function.  (See the section on functions.)
+.IP "\fBreturn\fR ( expression )"
+Return the value of the expression from a function.  (See the section on 
+functions.)  As an extension, the parenthesis are not required.
+.SS PSEUDO STATEMENTS
+These statements are not statements in the traditional sense.  They are
+not executed statements.  Their function is performed at "compile" time.
+.IP "\fBlimits\fR"
+Print the local limits enforced by the local version of \fBbc\fR.  This
+is an extension.
+.IP "\fBquit\fR"
+When the quit statement is read, the \fBbc\fR processor
+is terminated, regardless of where the quit statement is found.  For
+example, "if (0 == 1) quit" will cause \fBbc\fR to terminate.
+.IP "\fBwarranty\fR"
+Print a longer warranty notice.  This is an extension.
+.SS FUNCTIONS
+Functions provide a method of defining a computation that can be executed
+later.  Functions in 
+.B bc
+always compute a value and return it to the caller.  Function definitions
+are "dynamic" in the sense that a function is undefined until a definition
+is encountered in the input.  That definition is then used until another
+definition function for the same name is encountered.  The new definition
+then replaces the older definition.  A function is defined as follows:
+.nf
+.RS
+\fBdefine \fIname \fB( \fIparameters \fB) { \fInewline
+\fI    auto_list   statement_list \fB}\fR
+.RE
+.fi
+A function call is just an expression of the form
+"\fIname\fB(\fIparameters\fB)\fR".
+.PP
+Parameters are numbers or arrays (an extension).  In the function definition,
+zero or more parameters are defined by listing their names separated by
+commas.  Numbers are only call by value parameters.  Arrays are only
+call by variable.  Arrays are specified in the parameter definition by
+the notation "\fIname\fB[]\fR".   In the function call, actual parameters
+are full expressions for number parameters.  The same notation is used
+for passing arrays as for defining array parameters.  The named array is
+passed by variable to the function.  Since function definitions are dynamic,
+parameter numbers and types are checked when a function is called.  Any
+mismatch in number or types of parameters will cause a runtime error.
+A runtime error will also occur for the call to an undefined function.
+.PP
+The \fIauto_list\fR is an optional list of variables that are for
+"local" use.  The syntax of the auto list (if present) is "\fBauto
+\fIname\fR, ... ;".  (The semicolon is optional.)  Each \fIname\fR is
+the name of an auto variable.  Arrays may be specified by using the
+same notation as used in parameters.  These variables have their
+values pushed onto a stack at the start of the function.  The
+variables are then initialized to zero and used throughout the
+execution of the function.  At function exit, these variables are
+popped so that the original value (at the time of the function call)
+of these variables are restored.  The parameters are really auto
+variables that are initialized to a value provided in the function
+call.  Auto variables are different than traditional local variables
+because if function A calls function B, B may access function
+A's auto variables by just using the same name, unless function B has
+called them auto variables.  Due to the fact that auto variables and
+parameters are pushed onto a stack, \fBbc\fR supports recursive functions.
+.PP
+The function body is a list of \fBbc\fR statements.  Again, statements
+are separated by semicolons or newlines.  Return statements cause the
+termination of a function and the return of a value.  There are two
+versions of the return statement.  The first form, "\fBreturn\fR", returns
+the value 0 to the calling expression.  The second form, 
+"\fBreturn ( \fIexpression \fB)\fR", computes the value of the expression
+and returns that value to the calling expression.  There is an implied
+"\fBreturn (0)\fR" at the end of every function.  This allows a function
+to terminate and return 0 without an explicit return statement.
+.PP
+Functions also change the usage of the variable \fBibase\fR.  All
+constants in the function body will be converted using the value of
+\fBibase\fR at the time of the function call.  Changes of \fBibase\fR
+will be ignored during the execution of the function except for the
+standard function \fBread\fR, which will always use the current value
+of \fBibase\fR for conversion of numbers.
+.PP
+As an extension, the format of the definition has been slightly relaxed.
+The standard requires the opening brace be on the same line as the 
+\fBdefine\fR keyword and all other parts must be on following lines.
+This version of \fBbc\fR will allow any number of newlines before and
+after the opening brace of the function.  For example, the following
+definitions are legal.
+.nf
+.RS
+\f(CW
+define d (n) { return (2*n); }
+define d (n)
+  { return (2*n); }
+\fR
+.RE
+.fi
+.SS MATH LIBRARY
+If \fBbc\fR is invoked with the \fB-l\fR option, a math library is preloaded
+and the default scale is set to 20.   The math functions will calculate their
+results to the scale set at the time of their call.  
+The math library defines the following functions:
+.IP "s (\fIx\fR)"
+The sine of x, x is in radians.
+.IP "c (\fIx\fR)"
+The cosine of x, x is in radians.
+.IP "a (\fIx\fR)"
+The arctangent of x, arctangent returns radians.
+.IP "l (\fIx\fR)"
+The natural logarithm of x.
+.IP "e (\fIx\fR)"
+The exponential function of raising e to the value x.
+.IP "j (\fIn,x\fR)"
+The bessel function of integer order n of x.
+.SS EXAMPLES
+In /bin/sh,  the following will assign the value of "pi" to the shell
+variable \fBpi\fR.
+.RS
+\f(CW
+pi=$(echo "scale=10; 4*a(1)" | bc -l)
+\fR
+.RE
+.PP
+The following is the definition of the exponential function used in the
+math library.  This function is written in POSIX \fBbc\fR.
+.nf
+.RS
+\f(CW
+scale = 20
+
+/* Uses the fact that e^x = (e^(x/2))^2
+   When x is small enough, we use the series:
+     e^x = 1 + x + x^2/2! + x^3/3! + ...
+*/
+
+define e(x) {
+  auto  a, d, e, f, i, m, v, z
+
+  /* Check the sign of x. */
+  if (x<0) {
+    m = 1
+    x = -x
+  } 
+
+  /* Precondition x. */
+  z = scale;
+  scale = 4 + z + .44*x;
+  while (x > 1) {
+    f += 1;
+    x /= 2;
+  }
+
+  /* Initialize the variables. */
+  v = 1+x
+  a = x
+  d = 1
+
+  for (i=2; 1; i++) {
+    e = (a *= x) / (d *= i)
+    if (e == 0) {
+      if (f>0) while (f--)  v = v*v;
+      scale = z
+      if (m) return (1/v);
+      return (v/1);
+    }
+    v += e
+  }
+}
+\fR
+.RE
+.fi
+.PP
+The following is code that uses the extended features of \fBbc\fR to
+implement a simple program for calculating checkbook balances.  This
+program is best kept in a file so that it can be used many times 
+without having to retype it at every use.
+.nf
+.RS
+\f(CW
+scale=2
+print "\enCheck book program!\en"
+print "  Remember, deposits are negative transactions.\en"
+print "  Exit by a 0 transaction.\en\en"
+
+print "Initial balance? "; bal = read()
+bal /= 1
+print "\en"
+while (1) {
+  "current balance = "; bal
+  "transaction? "; trans = read()
+  if (trans == 0) break;
+  bal -= trans
+  bal /= 1
+}
+quit
+\fR
+.RE
+.fi
+.PP
+The following is the definition of the recursive factorial function.
+.nf
+.RS
+\f(CW
+define f (x) {
+  if (x <= 1) return (1);
+  return (f(x-1) * x);
+}
+\fR
+.RE
+.fi
+.SS READLINE AND LIBEDIT OPTIONS
+GNU \fBbc\fR can be compiled (via a configure option) to use the GNU
+\fBreadline\fR input editor library or the BSD \fBlibedit\fR library.
+This allows the user to do editing of lines before sending them
+to \fBbc\fR.  It also allows for a history of previous lines typed.
+When this option is selected, \fBbc\fR has one more special variable.
+This special variable, \fBhistory\fR is the number of lines of history
+retained.  For \fBreadline\fR, a value of -1 means that an unlimited
+number of history lines are retained.  Setting the value of
+\fBhistory\fR to a positive number restricts the number of history
+lines to the number given.  The value of 0 disables the history
+feature.  The default value is 100. For more information, read the
+user manuals for the GNU \fBreadline\fR, \fBhistory\fR and BSD \fBlibedit\fR
+libraries.  One can not enable both \fBreadline\fR and \fBlibedit\fR
+at the same time.
+.SS DIFFERENCES
+This version of 
+.B bc
+was implemented from the POSIX P1003.2/D11 draft and contains
+several differences and extensions relative to the draft and
+traditional implementations.
+It is not implemented in the traditional way using
+.I dc(1).
+This version is a single process which parses and runs a byte code
+translation of the program.  There is an "undocumented" option (-c)
+that causes the program to output the byte code to
+the standard output instead of running it.  It was mainly used for
+debugging the parser and preparing the math library.
+.PP
+A major source of differences is
+extensions, where a feature is extended to add more functionality and
+additions, where new features are added. 
+The following is the list of differences and extensions.
+.IP LANG environment
+This version does not conform to the POSIX standard in the processing
+of the LANG environment variable and all environment variables starting
+with LC_.
+.IP names
+Traditional and POSIX
+.B bc
+have single letter names for functions, variables and arrays.  They have
+been extended to be multi-character names that start with a letter and
+may contain letters, numbers and the underscore character.
+.IP Strings
+Strings are not allowed to contain NUL characters.  POSIX says all characters
+must be included in strings.
+.IP last
+POSIX \fBbc\fR does not have a \fBlast\fR variable.  Some implementations
+of \fBbc\fR use the period (.) in a similar way.  
+.IP comparisons
+POSIX \fBbc\fR allows comparisons only in the if statement, the while
+statement, and the second expression of the for statement.  Also, only
+one relational operation is allowed in each of those statements.
+.IP "if statement, else clause"
+POSIX \fBbc\fR does not have an else clause.
+.IP "for statement"
+POSIX \fBbc\fR requires all expressions to be present in the for statement.
+.IP "&&, ||, !"
+POSIX \fBbc\fR does not have the logical operators.
+.IP "read function"
+POSIX \fBbc\fR does not have a read function.
+.IP "print statement"
+POSIX \fBbc\fR does not have a print statement .
+.IP "continue statement"
+POSIX \fBbc\fR does not have a continue statement.
+.IP "return statement"
+POSIX \fBbc\fR requires parentheses around the return expression.
+.IP "array parameters"
+POSIX \fBbc\fR does not (currently) support array parameters in full.
+The POSIX grammar allows for arrays in function definitions, but does
+not provide a method to specify an array as an actual parameter.  (This
+is most likely an oversight in the grammar.)  Traditional implementations
+of \fBbc\fR have only call by value array parameters.
+.IP "function format"
+POSIX \fBbc\fR requires the opening brace on the same line as the 
+\fBdefine\fR key word and the \fBauto\fR statement on the next line.
+.IP "=+, =-, =*, =/, =%, =^"
+POSIX \fBbc\fR does not require these "old style" assignment operators to
+be defined.  This version may allow these "old style" assignments.  Use
+the limits statement to see if the installed version supports them.  If
+it does support the "old style" assignment operators, the statement
+"a =- 1" will decrement \fBa\fR by 1 instead of setting \fBa\fR to the
+value -1.
+.IP "spaces in numbers"
+Other implementations of \fBbc\fR allow spaces in numbers.  For example,
+"x=1 3" would assign the value 13 to the variable x.  The same statement
+would cause a syntax error in this version of \fBbc\fR.
+.IP "errors and execution"
+This implementation varies from other implementations in terms of what
+code will be executed when syntax and other errors are found in the
+program.  If a syntax error is found in a function definition, error
+recovery tries to find the beginning of a statement and continue to
+parse the function.  Once a syntax error is found in the function, the
+function will not be callable and becomes undefined.
+Syntax errors in the interactive execution code will invalidate the
+current execution block.  The execution block is terminated by an
+end of line that appears after a complete sequence of statements.
+For example, 
+.nf
+.RS
+a = 1
+b = 2
+.RE
+.fi
+has two execution blocks and
+.nf
+.RS
+{ a = 1
+  b = 2 }
+.RE
+.fi
+has one execution block.  Any runtime error will terminate the execution
+of the current execution block.  A runtime warning will not terminate the
+current execution block.
+.IP "Interrupts"
+During an interactive session, the SIGINT signal (usually generated by
+the control-C character from the terminal) will cause execution of the
+current execution block to be interrupted.  It will display a "runtime"
+error indicating which function was interrupted.  After all runtime
+structures have been cleaned up, a message will be printed to notify the
+user that \fBbc\fR is ready for more input.  All previously defined functions
+remain defined and the value of all non-auto variables are the value at
+the point of interruption.  All auto variables and function parameters
+are removed during the
+clean up process.  During a non-interactive
+session, the SIGINT signal will terminate the entire run of \fBbc\fR.
+.SS LIMITS
+The following are the limits currently in place for this 
+.B bc
+processor.  Some of them may have been changed by an installation.
+Use the limits statement to see the actual values.
+.IP BC_BASE_MAX
+The maximum output base is currently set at 999.  The maximum input base
+is 16.
+.IP BC_DIM_MAX
+This is currently an arbitrary limit of 65535 as distributed.  Your
+installation may be different.
+.IP BC_SCALE_MAX
+The number of digits after the decimal point is limited to INT_MAX digits.
+Also, the number of digits before the decimal point is limited to INT_MAX
+digits.
+.IP BC_STRING_MAX
+The limit on the number of characters in a string is INT_MAX characters.
+.IP exponent
+The value of the exponent in the raise operation (^) is limited to LONG_MAX.
+.IP "variable names"
+The current limit on the number of unique names is 32767 for each of
+simple variables, arrays and functions.
+.SH ENVIRONMENT VARIABLES
+The following environment variables are processed by \fBbc\fR:
+.IP "POSIXLY_CORRECT"
+This is the same as the \fB-s\fR option.
+.IP "BC_ENV_ARGS"
+This is another mechanism to get arguments to \fBbc\fR.  The
+format is the same as the command line arguments.  These arguments
+are processed first, so any files listed in the environent arguments
+are processed before any command line argument files.  This allows
+the user to set up "standard" options and files to be processed
+at every invocation of \fBbc\fR.  The files in the environment
+variables would typically contain function definitions for functions
+the user wants defined every time \fBbc\fR is run.
+.IP "BC_LINE_LENGTH"
+This should be an integer specifing the number of characters in an
+output line for numbers. This includes the backslash and newline characters
+for long numbers.
+.SH DIAGNOSTICS
+If any file on the command line can not be opened, \fBbc\fR will report
+that the file is unavailable and terminate.  Also, there are compile
+and run time diagnostics that should be self-explanatory.
+.SH BUGS
+Error recovery is not very good yet.
+.PP
+Email bug reports to
+.BR bug-bc@gnu.org .
+Be sure to include the word ``bc'' somewhere in the ``Subject:'' field.
+.SH AUTHOR
+.nf
+Philip A. Nelson
+philnelson@acm.org
+.fi
+.SH ACKNOWLEDGEMENTS
+The author would like to thank Steve Sommars (Steve.Sommars@att.com) for
+his extensive help in testing the implementation.  Many great suggestions
+were given.  This is a much better product due to his involvement.
diff --git a/doc/bc.info b/doc/bc.info
new file mode 100644 (file)
index 0000000..2e6648b
--- /dev/null
@@ -0,0 +1,1004 @@
+This is bc.info, produced by makeinfo version 4.0 from bc.texi.
+
+START-INFO-DIR-ENTRY
+* bc: (bc).                   An arbritrary precision calculator language
+END-INFO-DIR-ENTRY
+
+
+\1f
+File: bc.info,  Node: Top,  Next: Introduction,  Prev: (dir),  Up: (dir)
+
+* Menu:
+
+* Introduction::
+* Basic Elements::
+* Expressions::
+* Statements::
+* Functions::
+* Examples::
+* Readline and Libedit Options::
+* GNU `bc' and Other Implementations::
+* Limits::
+* Environment Variables::
+
+\1f
+File: bc.info,  Node: Introduction,  Next: Basic Elements,  Prev: Top,  Up: Top
+
+Introduction
+************
+
+* Menu:
+
+* Description::
+* Command Line Options::
+
+\1f
+File: bc.info,  Node: Description,  Next: Command Line Options,  Prev: Introduction,  Up: Introduction
+
+Description
+===========
+
+   `bc' [ -hlwsqv ] [long-options] [  FILE ... ]
+
+   `bc' is a language that supports arbitrary precision numbers with
+interactive execution of statements.  There are some similarities in
+the syntax to the C programming language.  A standard math library is
+available by command line option.  If requested, the math library is
+defined before processing any files.  `bc' starts by processing code
+from all the files listed on the command line in the order listed.
+After all files have been processed, `bc' reads from the standard
+input.  All code is executed as it is read.  (If a file contains a
+command to halt the processor, `bc' will never read from the standard
+input.)
+
+   This version of `bc' contains several extensions beyond traditional
+`bc' implementations and the POSIX draft standard.  Command line
+options can cause these extensions to print a warning or to be
+rejected.  This document describes the language accepted by this
+processor.  Extensions will be identified as such.
+
+   The author would like to thank Steve Sommars
+(<Steve.Sommars@att.com>) for his extensive help in testing the
+implementation.  Many great suggestions were given.  This is a much
+better product due to his involvement.
+
+   Email bug reports to <bug-bc@gnu.org>.  Be sure to include the word
+"bc" somewhere in the "Subject:" field.
+
+\1f
+File: bc.info,  Node: Command Line Options,  Next: Numbers,  Prev: Description,  Up: Introduction
+
+Command Line Options
+====================
+
+   `bc' takes the following options from the command line:
+`-h, --help'
+     Print the usage and exit.
+
+`-l, --mathlib'
+     Define the standard math library.
+
+`-w, --warn'
+     Give warnings for extensions to POSIX `bc'.
+
+`-s, --standard'
+     Process exactly the POSIX `bc' language.
+
+`-q, --quiet'
+     Do not print the normal GNU `bc' welcome.
+
+`-v, --version'
+     Print the version number and copyright and quit.
+
+\1f
+File: bc.info,  Node: Basic Elements,  Next: Expressions,  Prev: Introduction,  Up: Top
+
+Basic Elements
+**************
+
+* Menu:
+
+* Numbers::
+* Variables::
+* Comments::
+
+\1f
+File: bc.info,  Node: Numbers,  Next: Variables,  Prev: Command Line Options,  Up: Basic Elements
+
+Numbers
+=======
+
+   The most basic element in `bc' is the number.  Numbers are arbitrary
+precision numbers.  This precision is both in the integer part and the
+fractional part.  All numbers are represented internally in decimal and
+all computation is done in decimal.  (This version truncates results
+from divide and multiply operations.)  There are two attributes of
+numbers, the length and the scale.  The length is the total number of
+significant decimal digits in a number and the scale is the total number
+of decimal digits after the decimal point.  For example, .000001 has a
+length of 6 and scale of 6, while 1935.000 has a length of 7 and a scale
+of 3.
+
+\1f
+File: bc.info,  Node: Variables,  Next: Comments,  Prev: Numbers,  Up: Basic Elements
+
+Variables
+=========
+
+   Numbers are stored in two types of variables, simple variables and
+arrays.  Both simple variables and array variables are named.  Names
+begin with a letter followed by any number of letters, digits and
+underscores.  All letters must be lower case.  (Full alphanumeric names
+are an extension. In POSIX `bc' all names are a single lower case
+letter.)  The type of variable is clear by the context because all
+array variable names will be followed by brackets ( [ ] ).
+
+   There are four special variables, SCALE, IBASE, OBASE, and LAST.
+SCALE defines how some operations use digits after the decimal point.
+The default value of SCALE is 0. IBASE and OBASE define the conversion
+base for input and output numbers.  The default for both input and
+output is base 10.  LAST (an extension) is a variable that has the
+value of the last printed number.  These will be discussed in further
+detail where appropriate.  All of these variables may have values
+assigned to them as well as used in expressions.
+
+\1f
+File: bc.info,  Node: Comments,  Prev: Variables,  Up: Basic Elements
+
+Comments
+========
+
+   Comments in `bc' start with the characters `/*' and end with the
+characters `*/'.  Comments may start anywhere and appear as a single
+space in the input.  (This causes comments to delimit other input
+items.  For example, a comment can not be found in the middle of a
+variable name.)  Comments include any newlines (end of line) between
+the start and the end of the comment.
+
+   To support the use of scripts for `bc', a single line comment has
+been added as an extension.  A single line comment starts at a `#'
+character and continues to the next end of the line.  The end of line
+character is not part of the comment and is processed normally.
+
+\1f
+File: bc.info,  Node: Expressions,  Next: Statements,  Prev: Basic Elements,  Up: Top
+
+Expressions
+***********
+
+* Menu:
+
+* About Expressions and Special Variables::
+* Basic Expressions::
+* Relational Expressions::
+* Boolean Expressions::
+* Precedence::
+* Special Expressions::
+
+\1f
+File: bc.info,  Node: About Expressions and Special Variables,  Next: Basic Expressions,  Prev: Expressions,  Up: Expressions
+
+About Expressions and Special Variables
+=======================================
+
+   The numbers are manipulated by expressions and statements.  Since
+the language was designed to be interactive, statements and expressions
+are executed as soon as possible.  There is no main program.  Instead,
+code is executed as it is encountered.  (Functions, discussed in detail
+later, are defined when encountered.)
+
+   A simple expression is just a constant. `bc' converts constants into
+internal decimal numbers using the current input base, specified by the
+variable IBASE. (There is an exception in functions.)  The legal values
+of IBASE are 2 through 16.  Assigning a value outside this range to
+IBASE will result in a value of 2 or 16.  Input numbers may contain the
+characters 0-9 and A-F. (Note: They must be capitals.  Lower case
+letters are variable names.)  Single digit numbers always have the
+value of the digit regardless of the value of IBASE. (i.e. A = 10.)
+For multi-digit numbers, `bc' changes all input digits greater or equal
+to IBASE to the value of IBASE-1.  This makes the number `FFF' always
+be the largest 3 digit number of the input base.
+
+   Full expressions are similar to many other high level languages.
+Since there is only one kind of number, there are no rules for mixing
+types.  Instead, there are rules on the scale of expressions.  Every
+expression has a scale.  This is derived from the scale of original
+numbers, the operation performed and in many cases, the value of the
+variable SCALE. Legal values of the variable SCALE are 0 to the maximum
+number representable by a C integer.
+
+\1f
+File: bc.info,  Node: Basic Expressions,  Next: Relational Expressions,  Prev: About Expressions and Special Variables,  Up: Expressions
+
+Basic Expressions
+=================
+
+   In the following descriptions of legal expressions, "expr" refers to
+a complete expression and "VAR" refers to a simple or an array variable.
+A simple variable is just a
+
+   NAME
+
+   and an array variable is specified as
+
+   NAME[EXPR]
+
+   Unless specifically mentioned the scale of the result is the maximum
+scale of the expressions involved.
+
+`- expr'
+     The result is the negation of the expression.
+
+`++ VAR'
+     The variable is incremented by one and the new value is the result
+     of the expression.
+
+`-- VAR'
+     The variable is decremented by one and the new value is the result
+     of the expression.
+
+`VAR ++'
+     The result of the expression is the value of the variable and then
+     the variable is incremented by one.
+
+`VAR --'
+     The result of the expression is the value of the variable and then
+     the variable is decremented by one.
+
+`expr + expr'
+     The result of the expression is the sum of the two expressions.
+
+`expr - expr'
+     The result of the expression is the difference of the two
+     expressions.
+
+`expr * expr'
+     The result of the expression is the product of the two expressions.
+
+`expr / expr'
+     The result of the expression is the quotient of the two
+     expressions.  The scale of the result is the value of the variable
+     `scale'
+
+`expr % expr'
+     The result of the expression is the "remainder" and it is computed
+     in the following way.  To compute a%b, first a/b is computed to
+     SCALE digits.  That result is used to compute a-(a/b)*b to the
+     scale of the maximum of SCALE+scale(b) and scale(a).  If SCALE is
+     set to zero and both expressions are integers this expression is
+     the integer remainder function.
+
+`expr ^ expr'
+     The result of the expression is the value of the first raised to
+     the second. The second expression must be an integer.  (If the
+     second expression is not an integer, a warning is generated and the
+     expression is truncated to get an integer value.)  The scale of the
+     result is SCALE if the exponent is negative.  If the exponent is
+     positive the scale of the result is the minimum of the scale of the
+     first expression times the value of the exponent and the maximum of
+     SCALE and the scale of the first expression.  (e.g. scale(a^b) =
+     min(scale(a)*b, max(SCALE, scale(a))).)  It should be noted that
+     expr^0 will always return the value of 1.
+
+`( expr )'
+     This alters the standard precedence to force the evaluation of the
+     expression.
+
+`VAR = expr'
+     The variable is assigned the value of the expression.
+
+`VAR <op>= expr'
+     This is equivalent to "VAR = VAR <op> expr" with the exception
+     that the "VAR" part is evaluated only once.  This can make a
+     difference if "VAR" is an array.
+
+\1f
+File: bc.info,  Node: Relational Expressions,  Next: Boolean Expressions,  Prev: Basic Expressions,  Up: Expressions
+
+Relational Expressions
+======================
+
+   Relational expressions are a special kind of expression that always
+evaluate to 0 or 1, 0 if the relation is false and 1 if the relation is
+true.  These may appear in any legal expression.  (POSIX `bc' requires
+that relational expressions are used only in `if', `while', and `for'
+statements and that only one relational test may be done in them.)  The
+relational operators are
+
+`expr1 < expr2'
+     The result is 1 if expr1 is strictly less than expr2.
+
+`expr1 <= expr2'
+     The result is 1 if expr1 is less than or equal to expr2.
+
+`expr1 > expr2'
+     The result is 1 if expr1 is strictly greater than expr2.
+
+`expr1 >= expr2'
+     The result is 1 if expr1 is greater than or equal to expr2.
+
+`expr1 == expr2'
+     The result is 1 if expr1 is equal to expr2.
+
+`expr1 != expr2'
+     The result is 1 if expr1 is not equal to expr2.
+
+\1f
+File: bc.info,  Node: Boolean Expressions,  Next: Precedence,  Prev: Relational Expressions,  Up: Expressions
+
+Boolean Expressions
+===================
+
+   Boolean operations are also legal.  (POSIX `bc' does NOT have
+boolean operations). The result of all boolean operations are 0 and 1
+(for false and true) as in relational expressions.  The boolean
+operators are:
+
+`!expr'
+     The result is 1 if expr is 0.
+
+`expr && expr'
+     The result is 1 if both expressions are non-zero.
+
+`expr || expr'
+     The result is 1 if either expression is non-zero.
+
+\1f
+File: bc.info,  Node: Precedence,  Next: Special Expressions,  Prev: Boolean Expressions,  Up: Expressions
+
+Precedence
+==========
+
+   The expression precedence is as follows: (lowest to highest)
+
+     || operator, left associative
+     && operator, left associative
+     ! operator, nonassociative
+     Relational operators, left associative
+     Assignment operator, right associative
+     + and - operators, left associative
+     *, / and % operators, left associative
+     ^ operator, right associative
+     unary - operator, nonassociative
+     ++ and -- operators, nonassociative
+
+   This precedence was chosen so that POSIX compliant `bc' programs
+will run correctly. This will cause the use of the relational and
+logical operators to have some unusual behavior when used with
+assignment expressions.  Consider the expression:
+
+     a = 3 < 5
+
+   Most C programmers would assume this would assign the result of "3 <
+5" (the value 1) to the variable "a".  What this does in `bc' is assign
+the value 3 to the variable "a" and then compare 3 to 5.  It is best to
+use parentheses when using relational and logical operators with the
+assignment operators.
+
+\1f
+File: bc.info,  Node: Special Expressions,  Prev: Precedence,  Up: Expressions
+
+Special Expressions
+===================
+
+   There are a few more special expressions that are provided in `bc'.
+These have to do with user-defined functions and standard functions.
+They all appear as "NAME`('PARAMETERS`)'".  *Note Functions::, for
+user-defined functions.  The standard functions are:
+
+`length ( expression )'
+     The value of the length function is the number of significant
+     digits in the expression.
+
+`read ( )'
+     The `read' function (an extension) will read a number from the
+     standard input, regardless of where the function occurs.  Beware,
+     this can cause problems with the mixing of data and program in the
+     standard input.  The best use for this function is in a previously
+     written program that needs input from the user, but never allows
+     program code to be input from the user.  The value of the `read'
+     function is the number read from the standard input using the
+     current value of the variable IBASE for the conversion base.
+
+`scale ( expression )'
+     The value of the `scale' function is the number of digits after the
+     decimal point in the expression.
+
+`sqrt ( expression )'
+     The value of the `sqrt' function is the square root of the
+     expression.  If the expression is negative, a run time error is
+     generated.
+
+\1f
+File: bc.info,  Node: Statements,  Next: Functions,  Prev: Expressions,  Up: Top
+
+Statements
+**********
+
+* Menu:
+
+* Pseudo Statements::
+
+   Statements (as in most algebraic languages) provide the sequencing of
+expression evaluation.  In `bc' statements are executed "as soon as
+possible."  Execution happens when a newline in encountered and there
+is one or more complete statements.  Due to this immediate execution,
+newlines are very important in `bc'. In fact, both a semicolon and a
+newline are used as statement separators.  An improperly placed newline
+will cause a syntax error.  Because newlines are statement separators,
+it is possible to hide a newline by using the backslash character.  The
+sequence "\<nl>", where <nl> is the newline appears to `bc' as
+whitespace instead of a newline.  A statement list is a series of
+statements separated by semicolons and newlines.  The following is a
+list of `bc' statements and what they do: (Things enclosed in brackets
+( [ ] ) are optional parts of the statement.)
+
+EXPRESSION
+     This statement does one of two things.  If the expression starts
+     with "<variable> <assignment> ...", it is considered to be an
+     assignment statement.  If the expression is not an assignment
+     statement, the expression is evaluated and printed to the output.
+     After the number is printed, a newline is printed.  For example,
+     "a=1" is an assignment statement and "(a=1)" is an expression that
+     has an embedded assignment.  All numbers that are printed are
+     printed in the base specified by the variable OBASE. The legal
+     values for OBASE are 2 through BC_BASE_MAX (*note Environment
+     Variables::).  For bases 2 through 16, the usual method of writing
+     numbers is used.  For bases greater than 16, `bc' uses a
+     multi-character digit method of printing the numbers where each
+     higher base digit is printed as a base 10 number.  The
+     multi-character digits are separated by spaces.  Each digit
+     contains the number of characters required to represent the base
+     ten value of "OBASE -1".  Since numbers are of arbitrary
+     precision, some numbers may not be printable on a single output
+     line.  These long numbers will be split across lines using the "\"
+     as the last character on a line.  The maximum number of characters
+     printed per line is 70.  Due to the interactive nature of `bc',
+     printing a number causes the side effect of assigning the printed
+     value to the special variable LAST. This allows the user to
+     recover the last value printed without having to retype the
+     expression that printed the number.  Assigning to LAST is legal
+     and will overwrite the last printed value with the assigned value.
+     The newly assigned value will remain until the next number is
+     printed or another value is assigned to LAST.  (Some installations
+     may allow the use of a single period (.) which is not part of a
+     number as a short hand notation for for LAST.)
+
+STRING
+     The string is printed to the output.  Strings start with a double
+     quote character and contain all characters until the next double
+     quote character.  All characters are taken literally, including
+     any newline.  No newline character is printed after the string.
+
+`PRINT' LIST
+     The `print' statement (an extension) provides another method of
+     output.  The LIST is a list of strings and expressions separated by
+     commas.  Each string or expression is printed in the order of the
+     list.  No terminating newline is printed.  Expressions are
+     evaluated and their value is printed and assigned to the variable
+     `last'. Strings in the print statement are printed to the output
+     and may contain special characters.  Special characters start with
+     the backslash character (\e).  The special characters recognized
+     by `bc' are "a" (alert or bell), "b" (backspace), "f" (form feed),
+     "n" (newline), "r" (carriage return), "q" (double quote), "t"
+     (tab), and "\e" (backslash).  Any other character following the
+     backslash will be ignored.
+
+{ STATEMENT_LIST }
+     This is the compound statement.  It allows multiple statements to
+     be grouped together for execution.
+
+`IF' ( EXPRESSION ) STATEMENT1 [`ELSE' STATEMENT2]
+     The if statement evaluates the expression and executes statement1
+     or statement2 depending on the value of the expression.  If the
+     expression is non-zero, statement1 is executed.  If statement2 is
+     present and the value of the expression is 0, then statement2 is
+     executed.  (The `else' clause is an extension.)
+
+`WHILE' ( EXPRESSION ) STATEMENT
+     The while statement will execute the statement while the expression
+     is non-zero.  It evaluates the expression before each execution of
+     the statement.   Termination of the loop is caused by a zero
+     expression value or the execution of a `break' statement.
+
+`FOR' ( [EXPRESSION1] ; [EXPRESSION2] ; [EXPRESSION3] ) STATEMENT
+     The `for' statement controls repeated execution of the statement.
+     EXPRESSION1 is evaluated before the loop.  EXPRESSION2 is
+     evaluated before each execution of the statement.  If it is
+     non-zero, the statement is evaluated.  If it is zero, the loop is
+     terminated.  After each execution of the statement, EXPRESSION3 is
+     evaluated before the reevaluation of expression2.  If EXPRESSION1
+     or EXPRESSION3 are missing, nothing is evaluated at the point they
+     would be evaluated.  If EXPRESSION2 is missing, it is the same as
+     substituting the value 1 for EXPRESSION2.  (The optional
+     expressions are an extension. POSIX `bc' requires all three
+     expressions.)  The following is equivalent code for the `for'
+     statement:
+
+          expression1;
+          while (expression2) {
+             statement;
+             expression3;
+          }
+
+`BREAK'
+     This statement causes a forced exit of the most recent enclosing
+     `while' statement or `for' statement.
+
+`CONTINUE'
+     The `continue' statement (an extension)  causes the most recent
+     enclosing `for' statement to start the next iteration.
+
+`HALT'
+     The `halt' statement (an extension) is an executed statement that
+     causes the `bc' processor to quit only when it is executed.  For
+     example, "if (0 == 1) halt" will not cause `bc' to terminate
+     because the `halt' is not executed.
+
+`RETURN'
+     Return the value 0 from a function.  (*Note Functions::.)
+
+`RETURN' ( EXPRESSION )
+     Return the value of the expression from a function.  (*Note
+     Functions::.)  As an extension, the parenthesis are not required.
+
+\1f
+File: bc.info,  Node: Pseudo Statements,  Prev: Statements,  Up: Statements
+
+Pseudo Statements
+=================
+
+   These statements are not statements in the traditional sense.  They
+are not executed statements.  Their function is performed at "compile"
+time.
+
+`limits'
+     Print the local limits enforced by the local version of `bc'.  This
+     is an extension.
+
+`quit'
+     When the `quit' statement is read, the `bc' processor is
+     terminated, regardless of where the `quit' statement is found.  For
+     example, "if (0 == 1) quit" will cause `bc' to terminate.
+
+`warranty'
+     Print a longer warranty notice.  This is an extension.
+
+\1f
+File: bc.info,  Node: Functions,  Next: Examples,  Prev: Statements,  Up: Top
+
+Functions
+*********
+
+* Menu:
+
+* Math Library Functions::
+
+   Functions provide a method of defining a computation that can be
+executed later.  Functions in `bc' always compute a value and return it
+to the caller.  Function definitions are "dynamic" in the sense that a
+function is undefined until a definition is encountered in the input.
+That definition is then used until another definition function for the
+same name is encountered.  The new definition then replaces the older
+definition.  A function is defined as follows:
+
+     `define' NAME `(' PARAMETERS `)' `{' NEWLINE
+         AUTO_LIST   STATEMENT_LIST `}'
+
+   A function call is just an expression of the form "`name'
+`('PARAMETERS`)'".
+
+   Parameters are numbers or arrays (an extension).  In the function
+definition, zero or more parameters are defined by listing their names
+separated by commas.  Numbers are only call by value parameters.
+Arrays are only call by variable.  Arrays are specified in the
+parameter definition by the notation "NAME`[ ]'".   In the function
+call, actual parameters are full expressions for number parameters.
+The same notation is used for passing arrays as for defining array
+parameters.  The named array is passed by variable to the function.
+Since function definitions are dynamic, parameter numbers and types are
+checked when a function is called.  Any mismatch in number or types of
+parameters will cause a runtime error.  A runtime error will also occur
+for the call to an undefined function.
+
+   The AUTO_LIST is an optional list of variables that are for "local"
+use.  The syntax of the auto list (if present) is "`auto' NAME, ... ;".
+(The semicolon is optional.)  Each NAME is the name of an auto
+variable.  Arrays may be specified by using the same notation as used
+in parameters.  These variables have their values pushed onto a stack
+at the start of the function.  The variables are then initialized to
+zero and used throughout the execution of the function.  At function
+exit, these variables are popped so that the original value (at the
+time of the function call) of these variables are restored.  The
+parameters are really auto variables that are initialized to a value
+provided in the function call.  Auto variables are different than
+traditional local variables because if function A calls function B, B
+may access function A's auto variables by just using the same name,
+unless function B has called them auto variables.  Due to the fact that
+auto variables and parameters are pushed onto a stack, `bc' supports
+recursive functions.
+
+   The function body is a list of `bc' statements.  Again, statements
+are separated by semicolons or newlines.  Return statements cause the
+termination of a function and the return of a value.  There are two
+versions of the return statement.  The first form, "`return'", returns
+the value 0 to the calling expression.  The second form, "`return' (
+EXPRESSION )", computes the value of the expression and returns that
+value to the calling expression.  There is an implied "`return' (0)" at
+the end of every function.  This allows a function to terminate and
+return 0 without an explicit `return' statement.
+
+   Functions also change the usage of the variable IBASE.  All
+constants in the function body will be converted using the value of
+IBASE at the time of the function call.  Changes of IBASE will be
+ignored during the execution of the function except for the standard
+function `read', which will always use the current value of IBASE for
+conversion of numbers.
+
+   As an extension, the format of the definition has been slightly
+relaxed.  The standard requires the opening brace be on the same line
+as the `define' keyword and all other parts must be on following lines.
+This version of `bc' will allow any number of newlines before and after
+the opening brace of the function.  For example, the following
+definitions are legal.
+
+        define d (n) { return (2*n); }
+        define d (n)
+            { return (2*n); }
+
+\1f
+File: bc.info,  Node: Math Library Functions,  Prev: Functions,  Up: Functions
+
+Math Library Functions
+======================
+
+   If `bc' is invoked with the `-l' option, a math library is preloaded
+and the default SCALE is set to 20.  The math functions will calculate
+their results to the scale set at the time of their call.  The math
+library defines the following functions:
+
+`s (X)'
+     The sine of X, X is in radians.
+
+`c (X)'
+     The cosine of X, X is in radians.
+
+`a (X)'
+     The arctangent of X, arctangent returns radians.
+
+`l (X)'
+     The natural logarithm of X.
+
+`E (X)'
+     The exponential function of raising E to the value X.
+
+`J (N,X)'
+     The bessel function of integer order N of X.
+
+\1f
+File: bc.info,  Node: Examples,  Next: Readline and Libedit Options,  Prev: Functions,  Up: Top
+
+Examples
+********
+
+   In /bin/sh,  the following will assign the value of "pi" to the shell
+variable PI.
+
+     pi=$(echo "scale=10; 4*a(1)" | bc -l)
+
+   The following is the definition of the exponential function used in
+the math library.  This function is written in POSIX `bc'.
+
+
+     scale = 20
+     
+     /* Uses the fact that e^x = (e^(x/2))^2
+        When x is small enough, we use the series:
+          e^x = 1 + x + x^2/2! + x^3/3! + ...
+     */
+     
+     define e(x) {
+       auto  a, d, e, f, i, m, v, z
+     
+       /* Check the sign of x. */
+       if (x<0) {
+         m = 1
+         x = -x
+       }
+     
+       /* Precondition x. */
+       z = scale;
+       scale = 4 + z + .44*x;
+       while (x > 1) {
+         f += 1;
+         x /= 2;
+       }
+     
+       /* Initialize the variables. */
+       v = 1+x
+       a = x
+       d = 1
+     
+       for (i=2; 1; i++) {
+         e = (a *= x) / (d *= i)
+         if (e == 0) {
+           if (f>0) while (f--)  v = v*v;
+           scale = z
+           if (m) return (1/v);
+           return (v/1);
+         }
+         v += e
+       }
+     }
+
+   The following is code that uses the extended features of `bc' to
+implement a simple program for calculating checkbook balances.  This
+program is best kept in a file so that it can be used many times
+without having to retype it at every use.
+
+
+     scale=2
+     print "\nCheck book program\n!"
+     print "  Remember, deposits are negative transactions.\n"
+     print "  Exit by a 0 transaction.\n\n"
+     
+     print "Initial balance? "; bal = read()
+     bal /= 1
+     print "\n"
+     while (1) {
+       "current balance = "; bal
+       "transaction? "; trans = read()
+       if (trans == 0) break;
+       bal -= trans
+       bal /= 1
+     }
+     quit
+
+   The following is the definition of the recursive factorial function.
+
+
+     define f (x) {
+       if (x <= 1) return (1);
+       return (f(x-1) * x);
+     }
+
+\1f
+File: bc.info,  Node: Readline and Libedit Options,  Next: GNU `bc' and Other Implementations,  Prev: Examples,  Up: Top
+
+Readline and Libedit Options
+****************************
+
+   GNU `bc' can be compiled (via a configure option) to use the GNU
+`readline' input editor library or the BSD `libedit' library.  This
+allows the user to do more editing of lines before sending them to
+`bc'.  It also allows for a history of previous lines typed.  When this
+option is selected, `bc' has one more special variable.  This special
+variable, HISTORY is the number of lines of history retained.  A value
+of -1 means that an unlimited number of history lines are retained.
+This is the default value.  Setting the value of HISTORY to a positive
+number restricts the number of history lines to the number given.  The
+value of 0 disables the history feature.  For more information, read
+the user manuals for the GNU `readline', `history' and BSD `libedit'
+libraries.  One can not enable both `readline' and `libedit' at the
+same time.
+
+\1f
+File: bc.info,  Node: GNU `bc' and Other Implementations,  Next: Limits,  Prev: Readline and Libedit Options,  Up: Top
+
+GNU `bc' and Other Implementations
+**********************************
+
+   This version of `bc' was implemented from the POSIX P1003.2/D11
+draft and contains several differences and extensions relative to the
+draft and traditional implementations.  It is not implemented in the
+traditional way using `dc'.  This version is a single process which
+parses and runs a byte code translation of the program.  There is an
+"undocumented" option (-c) that causes the program to output the byte
+code to the standard output instead of running it.  It was mainly used
+for debugging the parser and preparing the math library.
+
+   A major source of differences is extensions, where a feature is
+extended to add more functionality and additions, where new features
+are added.  The following is the list of differences and extensions.
+
+LANG ENVIRONMENT
+     This version does not conform to the POSIX standard in the
+     processing of the LANG environment variable and all environment
+     variables starting with LC_.
+
+NAMES
+     Traditional and POSIX `bc' have single letter names for functions,
+     variables and arrays.  They have been extended to be
+     multi-character names that start with a letter and may contain
+     letters, numbers and the underscore character.
+
+STRINGS
+     Strings are not allowed to contain NUL characters.  POSIX says all
+     characters must be included in strings.
+
+LAST
+     POSIX `bc' does not have a \fBlast variable.  Some implementations
+     of `bc' use the period (.) in a similar way.
+
+COMPARISONS
+     POSIX `bc' allows comparisons only in the `if' statement, the
+     `while' statement, and the second expression of the `for'
+     statement.  Also, only one relational operation is allowed in each
+     of those statements.
+
+IF STATEMENT, ELSE CLAUSE
+     POSIX `bc' does not have an `else' clause.
+
+FOR STATEMENT
+     POSIX `bc' requires all expressions to be present in the `for'
+     statement.
+
+&&, ||, !
+     POSIX `bc' does not have the logical operators.
+
+READ FUNCTION
+     POSIX `bc' does not have a `read' function.
+
+PRINT STATEMENT
+     POSIX `bc' does not have a `print' statement.
+
+CONTINUE STATEMENT
+     POSIX `bc' does not have a continue statement.
+
+ARRAY PARAMETERS
+     POSIX `bc' does not (currently) support array parameters in full.
+     The POSIX grammar allows for arrays in function definitions, but
+     does not provide a method to specify an array as an actual
+     parameter.  (This is most likely an oversight in the grammar.)
+     Traditional implementations of `bc' have only call by value array
+     parameters.
+
+FUNCTION FORMAT
+     POSIX `bc' requires the opening brace on the same line as the
+     `define' key word and the `auto' statement on the next line.
+
+=+, =-, =*, =/, =%, =^
+     POSIX `bc' does not require these "old style" assignment operators
+     to be defined.  This version may allow these "old style"
+     assignments.  Use the `limits' statement to see if the installed
+     version supports them.  If it does support the "old style"
+     assignment operators, the statement "a =- 1" will decrement `a' by
+     1 instead of setting `a' to the value -1.
+
+SPACES IN NUMBERS
+     Other implementations of `bc' allow spaces in numbers.  For
+     example, "x=1 3" would assign the value 13 to the variable x.  The
+     same statement would cause a syntax error in this version of `bc'.
+
+ERRORS AND EXECUTION
+     This implementation varies from other implementations in terms of
+     what code will be executed when syntax and other errors are found
+     in the program.  If a syntax error is found in a function
+     definition, error recovery tries to find the beginning of a
+     statement and continue to parse the function.  Once a syntax error
+     is found in the function, the function will not be callable and
+     becomes undefined.  Syntax errors in the interactive execution
+     code will invalidate the current execution block.  The execution
+     block is terminated by an end of line that appears after a
+     complete sequence of statements.  For example,
+
+          a = 1
+          b = 2
+
+     has two execution blocks and
+
+          { a = 1
+            b = 2 }
+
+     has one execution block.  Any runtime error will terminate the
+     execution of the current execution block.  A runtime warning will
+     not terminate the current execution block.
+
+INTERRUPTS
+     During an interactive session, the SIGINT signal (usually
+     generated by the control-C character from the terminal) will cause
+     execution of the current execution block to be interrupted.  It
+     will display a "runtime" error indicating which function was
+     interrupted.  After all runtime structures have been cleaned up, a
+     message will be printed to notify the user that `bc' is ready for
+     more input.  All previously defined functions remain defined and
+     the value of all non-auto variables are the value at the point of
+     interruption.  All auto variables and function parameters are
+     removed during the clean up process.  During a non-interactive
+     session, the SIGINT signal will terminate the entire run of `bc'.
+
+\1f
+File: bc.info,  Node: Limits,  Next: Environment Variables,  Prev: GNU `bc' and Other Implementations,  Up: Top
+
+Limits
+******
+
+   The following are the limits currently in place for this `bc'
+processor.  Some of them may have been changed by an installation.  Use
+the `limits' statement to see the actual values.
+
+`BC_BASE_MAX'
+     The maximum output base is currently set at 999.  The maximum
+     input base is 16.
+
+`BC_DIM_MAX'
+     This is currently an arbitrary limit of 65535 as distributed.  Your
+     installation may be different.
+
+`BC_SCALE_MAX'
+     The number of digits after the decimal point is limited to INT_MAX
+     digits.  Also, the number of digits before the decimal point is
+     limited to INT_MAX digits.
+
+`BC_STRING_MAX'
+     The limit on the number of characters in a string is INT_MAX
+     characters.
+
+`exponent'
+     The value of the exponent in the raise operation (^) is limited to
+     LONG_MAX.
+
+`multiply'
+     The multiply routine may yield incorrect results if a number has
+     more than LONG_MAX / 90 total digits.  For 32 bit longs, this
+     number is 23,860,929 digits.
+
+`variable names'
+     The current limit on the number of unique names is 32767 for each
+     of simple variables, arrays and functions.
+
+\1f
+File: bc.info,  Node: Environment Variables,  Prev: Limits,  Up: Top
+
+Environment Variables
+*********************
+
+   The following environment variables are processed by `bc':
+
+`POSIXLY_CORRECT'
+     This is the same as the -s option (*note Command Line Options::).
+
+`BC_ENV_ARGS'
+     This is another mechanism to get arguments to `bc'.  The format is
+     the same as the command line arguments.  These arguments are
+     processed first, so any files listed in the environent arguments
+     are processed before any command line argument files.  This allows
+     the user to set up "standard" options and files to be processed at
+     every invocation of `bc'.  The files in the environment variables
+     would typically contain function definitions for functions the user
+     wants defined every time `bc' is run.
+
+`BC_LINE_LENGTH'
+     This should be an integer specifing the number of characters in an
+     output line for numbers. This includes the backslash and newline
+     characters for long numbers.
+
+
+\1f
+Tag Table:
+Node: Top\7f65
+Node: Introduction\7f354
+Node: Description\7f515
+Node: Command Line Options\7f1969
+Node: Basic Elements\7f2533
+Node: Numbers\7f2704
+Node: Variables\7f3467
+Node: Comments\7f4576
+Node: Expressions\7f5317
+Node: About Expressions and Special Variables\7f5597
+Node: Basic Expressions\7f7333
+Node: Relational Expressions\7f10274
+Node: Boolean Expressions\7f11279
+Node: Precedence\7f11834
+Node: Special Expressions\7f12994
+Node: Statements\7f14376
+Node: Pseudo Statements\7f21001
+Node: Functions\7f21649
+Node: Math Library Functions\7f25703
+Node: Examples\7f26413
+Node: Readline and Libedit Options\7f28431
+Node: GNU `bc' and Other Implementations\7f29458
+Node: Limits\7f34700
+Node: Environment Variables\7f35953
+\1f
+End Tag Table
diff --git a/doc/bc.texi b/doc/bc.texi
new file mode 100644 (file)
index 0000000..a7cb9f6
--- /dev/null
@@ -0,0 +1,1014 @@
+\input texinfo  @c -*-texinfo-*-
+@c %**start of header
+@setfilename bc.info
+@settitle bc Command Manual
+@c %**end of header
+
+@c This file has the new style title page commands.
+@c Run `makeinfo' rather than `texinfo-format-buffer'.
+
+@smallbook
+
+@c tex
+@c \overfullrule=0pt
+@c end tex
+
+@titlepage
+@title @command{bc}
+@subtitle an arbitrary precision calculator language
+@subtitle version 1.06
+
+@author Philip A. Nelson
+@page
+
+This manual documents @command{bc}, an arbitrary precision calculator language.
+
+This manual is part of GNU @command{bc}.@*
+@sp4
+Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@iftex
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end iftex
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+You may contact the author by:
+e-mail: @email{phil@@cs.wwu.edu}@*
+us-mail: Philip A. Nelson@*
+Computer Science Department, 9062@*
+Western Washington University@*
+Bellingham, WA 98226-9062
+
+@end titlepage
+
+@node Top, Introduction, (dir), (dir)
+
+@menu
+* Introduction::
+* Basic Elements::
+* Expressions::
+* Statements::
+* Functions::
+* Examples::
+* Readline and Libedit Options::
+* GNU @command{bc} and Other Implementations::
+* Limits::
+* Environment Variables::
+@end menu
+
+@node Introduction, Basic Elements, Top, Top
+@chapter Introduction
+@menu
+* Description::
+* Command Line Options::
+@end menu
+
+@node Description, Command Line Options, Introduction, Introduction
+@section Description
+
+@command{bc} [ -hlwsqv ] [long-options] [ @var{ file ...} ]
+
+@command{bc} is a language that supports arbitrary precision numbers
+with interactive execution of statements.  There are some similarities
+in the syntax to the C programming language. 
+A standard math library is available by command line option.
+If requested, the math library is defined before processing any files.
+@command{bc} starts by processing code from all the files listed
+on the command line in the order listed.  After all files have been
+processed, @command{bc} reads from the standard input.  All code is
+executed as it is read.  (If a file contains a command to halt the
+processor, @command{bc} will never read from the standard input.)
+
+This version of @command{bc} contains several extensions beyond
+traditional @command{bc} implementations and the POSIX draft standard.
+Command line options can cause these extensions to print a warning or to
+be rejected.  This document describes the language accepted by this
+processor.  Extensions will be identified as such.
+
+The author would like to thank Steve Sommars
+(@email{Steve.Sommars@@att.com}) for his extensive help in testing the
+implementation.  Many great suggestions were given.  This is a much
+better product due to his involvement.
+
+Email bug reports to @email{bug-bc@@gnu.org}.  Be sure to include
+the word ``bc'' somewhere in the ``Subject:'' field.
+
+@node Command Line Options, Numbers, Description, Introduction
+@section Command Line Options
+
+@command{bc} takes the following options from the command line:
+@table @code
+
+@item -h, --help
+Print the usage and exit.
+
+@item -l, --mathlib
+Define the standard math library.
+
+@item -w, --warn
+Give warnings for extensions to POSIX @command{bc}.
+
+@item -s, --standard
+Process exactly the POSIX @command{bc} language.
+
+@item -q, --quiet
+Do not print the normal GNU @command{bc} welcome.
+
+@item -v, --version 
+Print the version number and copyright and quit.
+
+@end table
+
+
+@node Basic Elements, Expressions, Introduction, Top
+@chapter Basic Elements
+@menu
+* Numbers::
+* Variables::
+* Comments::
+@end menu
+
+@node Numbers, Variables, Command Line Options, Basic Elements
+@section Numbers
+
+The most basic element in @command{bc} is the number.  Numbers are
+arbitrary precision numbers.  This precision is both in the integer part
+and the fractional part.  All numbers are represented internally in
+decimal and all computation is done in decimal.  (This version truncates
+results from divide and multiply operations.)  There are two attributes
+of numbers, the length and the scale.  The length is the total number of
+significant decimal digits in a number and the scale is the total number
+of decimal digits after the decimal point.  For example, .000001 has a
+length of 6 and scale of 6, while 1935.000 has a length of 7 and a scale
+of 3.
+
+@node Variables, Comments, Numbers, Basic Elements
+@section Variables
+
+Numbers are stored in two types of variables, simple variables and
+arrays.  Both simple variables and array variables are named.  Names
+begin with a letter followed by any number of letters, digits and
+underscores.  All letters must be lower case.  (Full alphanumeric
+names are an extension. In POSIX @command{bc} all names are a single
+lower case letter.)  The type of variable is clear by the context
+because all array variable names will be followed by brackets ( [ ] ).
+
+There are four special variables, @var{scale}, @var{ibase}, @var{obase}, and
+@var{last}.  @var{scale} defines how some operations use digits after the
+decimal point.  The default value of @var{scale} is 0. @var{ibase}
+and @var{obase} define the conversion base for input and output
+numbers.  The default for both input and output is base 10.
+@var{last} (an extension) is a variable that has the value of the last
+printed number.  These will be discussed in further detail where
+appropriate.  All of these variables may have values assigned to them
+as well as used in expressions.
+
+@node Comments, , Variables, Basic Elements
+@section Comments
+
+Comments in @command{bc} start with the characters @code{/*} and end with
+the characters @code{*/}.  Comments may start anywhere and appear as a
+single space in the input.  (This causes comments to delimit other
+input items.  For example, a comment can not be found in the middle of
+a variable name.)  Comments include any newlines (end of line) between
+the start and the end of the comment.
+
+To support the use of scripts for @command{bc}, a single line comment has been
+added as an extension.  A single line comment starts at a @code{#}
+character and continues to the next end of the line.  The end of line
+character is not part of the comment and is processed normally.
+
+@node Expressions, Statements, Basic Elements, Top
+@chapter Expressions
+
+@menu 
+* About Expressions and Special Variables::
+* Basic Expressions::
+* Relational Expressions::
+* Boolean Expressions::
+* Precedence::
+* Special Expressions::
+@end menu
+
+@node About Expressions and Special Variables, Basic Expressions, Expressions, Expressions
+@section About Expressions and Special Variables
+
+The numbers are manipulated by expressions and statements.  Since
+the language was designed to be interactive, statements and expressions
+are executed as soon as possible.  There is no main program.  Instead,
+code is executed as it is encountered.  (Functions, discussed in
+detail later, are defined when encountered.)
+
+A simple expression is just a constant. @command{bc} converts constants
+into internal decimal numbers using the current input base, specified by
+the variable @var{ibase}. (There is an exception in functions.)  The
+legal values of @var{ibase} are 2 through 16.  Assigning a value outside
+this range to @var{ibase} will result in a value of 2 or 16.  Input
+numbers may contain the characters 0-9 and A-F. (Note: They must be
+capitals.  Lower case letters are variable names.)  Single digit numbers
+always have the value of the digit regardless of the value of
+@var{ibase}. (i.e. A = 10.)  For multi-digit numbers, @command{bc}
+changes all input digits greater or equal to @var{ibase} to the value of
+@var{ibase}-1.  This makes the number @code{FFF} always be the largest
+3 digit number of the input base.
+
+Full expressions are similar to many other high level languages.
+Since there is only one kind of number, there are no rules for mixing
+types.  Instead, there are rules on the scale of expressions.  Every
+expression has a scale.  This is derived from the scale of original
+numbers, the operation performed and in many cases, the value of the
+variable @var{scale}. Legal values of the variable @var{scale} are
+0 to the maximum number representable by a C integer.
+
+@node Basic Expressions, Relational Expressions, About Expressions and Special Variables, Expressions
+@section Basic Expressions
+
+In the following descriptions of legal expressions, "expr" refers to a
+complete expression and "@var{var}" refers to a simple or an array variable.
+A simple variable is just a 
+
+@var{name}
+
+and an array variable is specified as 
+
+@var{name}[@var{expr}] 
+
+Unless specifically mentioned the scale of the result is the maximum
+scale of the expressions involved.
+
+@table @code
+@item - expr
+The result is the negation of the expression.
+
+@item ++ @var{var}
+The variable is incremented by one and the new value is the result of
+the expression.
+
+@item -- @var{var}
+The variable
+is decremented by one and the new value is the result of the
+expression.
+
+@item @var{var} ++
+ The result of the expression is the value of
+the variable and then the variable is incremented by one.
+
+@item @var{var} --
+The result of the expression is the value of the variable and then
+the variable is decremented by one.
+
+@item expr + expr
+The result of the expression is the sum of the two expressions.
+
+@item expr - expr
+The result of the expression is the difference of the two expressions.
+
+@item expr * expr
+The result of the expression is the product of the two expressions.
+
+@item expr / expr
+The result of the expression is the quotient of the two expressions.
+The scale of the result is the value of the variable @code{scale}
+
+@item expr % expr
+The result of the expression is the "remainder" and it is computed in the
+following way.  To compute a%b, first a/b is computed to @var{scale}
+digits.  That result is used to compute a-(a/b)*b to the scale of the
+maximum of @var{scale}+scale(b) and scale(a).  If @var{scale} is set
+to zero and both expressions are integers this expression is the
+integer remainder function.
+
+@item expr ^ expr
+The result of the expression is the value of the first raised to the
+second. The second expression must be an integer.  (If the second
+expression is not an integer, a warning is generated and the
+expression is truncated to get an integer value.)  The scale of the
+result is @var{scale} if the exponent is negative.  If the exponent
+is positive the scale of the result is the minimum of the scale of the
+first expression times the value of the exponent and the maximum of
+@var{scale} and the scale of the first expression.  (e.g. scale(a^b)
+= min(scale(a)*b, max(@var{scale}, scale(a))).)  It should be noted
+that expr^0 will always return the value of 1.
+
+@item ( expr )
+This alters the standard precedence to force the evaluation of the
+expression.
+
+@item @var{var} = expr
+The variable is assigned the value of the expression.
+
+@item @var{var} <op>= expr
+This is equivalent to "@var{var} = @var{var} <op> expr" with the
+exception that the "@var{var}" part is evaluated only once.  This can
+make a difference if "@var{var}" is an array.
+@end table
+
+@node Relational Expressions, Boolean Expressions, Basic Expressions, Expressions
+@section Relational Expressions
+
+Relational expressions are a special kind of expression that always
+evaluate to 0 or 1, 0 if the relation is false and 1 if the relation is
+true.  These may appear in any legal expression.  (POSIX @command{bc}
+requires that relational expressions are used only in @code{if},
+@code{while}, and @code{for} statements and that only one relational
+test may be done in them.)  The relational operators are
+
+@table @code
+@item expr1 < expr2
+The result is 1 if expr1 is strictly less than expr2.
+
+@item expr1 <= expr2
+The result is 1 if expr1 is less than or equal to expr2.
+
+@item expr1 > expr2
+The result is 1 if expr1 is strictly greater than expr2.
+
+@item expr1 >= expr2
+The result is 1 if expr1 is greater than or equal to expr2.
+
+@item expr1 == expr2
+The result is 1 if expr1 is equal to expr2.
+
+@item expr1 != expr2
+The result is 1 if expr1 is not equal to expr2.
+@end table
+
+@node Boolean Expressions, Precedence, Relational Expressions, Expressions
+@section Boolean Expressions
+
+Boolean operations are also legal.  (POSIX @command{bc} does NOT have
+boolean operations). The result of all boolean operations are 0 and 1
+(for false and true) as in relational expressions.  The boolean
+operators are:
+
+@table @code
+@item !expr
+The result is 1 if expr is 0.
+
+@item expr && expr
+The result is 1 if both expressions are non-zero.
+
+@item expr || expr
+The result is 1 if either expression is non-zero.
+@end table
+
+@node Precedence, Special Expressions, Boolean Expressions, Expressions
+@section Precedence
+
+The expression precedence is as follows: (lowest to highest)
+
+@example
+|| operator, left associative
+&& operator, left associative
+! operator, nonassociative
+Relational operators, left associative
+Assignment operator, right associative
++ and - operators, left associative
+*, / and % operators, left associative
+^ operator, right associative
+unary - operator, nonassociative
+++ and -- operators, nonassociative
+@end example
+
+This precedence was chosen so that POSIX compliant @command{bc} programs
+will run correctly. This will cause the use of the relational and
+logical operators to have some unusual behavior when used with
+assignment expressions.  Consider the expression:
+
+@example
+a = 3 < 5
+@end example
+
+Most C programmers would assume this would assign the result of "3 <
+5" (the value 1) to the variable "a".  What this does in @command{bc} is
+assign the value 3 to the variable "a" and then compare 3 to 5.  It is
+best to use parentheses when using relational and logical operators
+with the assignment operators.
+
+@node Special Expressions, , Precedence, Expressions
+@section Special Expressions
+
+There are a few more special expressions that are provided in
+@command{bc}.  These have to do with user-defined functions and standard
+functions.  They all appear as
+"@var{name}@code{(}@var{parameters}@code{)}".  @xref{Functions}, for
+user-defined functions.  The standard functions are:
+
+@table @code
+@item length ( expression )
+The value of the length function is the number of significant digits in the
+expression.
+
+@item read ( )
+The @code{read} function (an extension) will read a number from the
+standard input, regardless of where the function occurs.  Beware, this
+can cause problems with the mixing of data and program in the standard
+input.  The best use for this function is in a previously written
+program that needs input from the user, but never allows program code to
+be input from the user.  The value of the @code{read} function is the
+number read from the standard input using the current value of the
+variable @var{ibase} for the conversion base.
+
+@item scale ( expression )
+The value of the @code{scale} function is the number of digits after the
+decimal point in the expression.
+
+@item sqrt ( expression )
+The value of the @code{sqrt} function is the square root of the
+expression.  If the expression is negative, a run time error is
+generated.
+@end table
+
+@node Statements, Functions, Expressions, Top
+@chapter Statements
+
+@menu
+* Pseudo Statements::
+@end menu
+
+Statements (as in most algebraic languages) provide the sequencing of
+expression evaluation.  In @command{bc} statements are executed "as soon
+as possible."  Execution happens when a newline in encountered and there
+is one or more complete statements.  Due to this immediate execution,
+newlines are very important in @command{bc}. In fact, both a semicolon
+and a newline are used as statement separators.  An improperly placed
+newline will cause a syntax error.  Because newlines are statement
+separators, it is possible to hide a newline by using the backslash
+character.  The sequence "\<nl>", where <nl> is the newline appears to
+@command{bc} as whitespace instead of a newline.  A statement list is a
+series of statements separated by semicolons and newlines.  The
+following is a list of @command{bc} statements and what they do: (Things
+enclosed in brackets ( [ ] ) are optional parts of the statement.)
+
+@table @var
+@item expression
+This statement does one of two things.  If the expression starts with
+"<variable> <assignment> ...", it is considered to be an assignment
+statement.  If the expression is not an assignment statement, the
+expression is evaluated and printed to the output.  After the number is
+printed, a newline is printed.  For example, "a=1" is an assignment
+statement and "(a=1)" is an expression that has an embedded assignment.
+All numbers that are printed are printed in the base specified by the
+variable @var{obase}. The legal values for @var{obase} are 2 through
+BC_BASE_MAX (@pxref{Environment Variables}).  For bases 2 through 16,
+the usual method of writing numbers is used.  For bases greater than 16,
+@command{bc} uses a multi-character digit method of printing the numbers
+where each higher base digit is printed as a base 10 number.  The
+multi-character digits are separated by spaces.  Each digit contains the
+number of characters required to represent the base ten value of
+"@var{obase} -1".  Since numbers are of arbitrary precision, some
+numbers may not be printable on a single output line.  These long
+numbers will be split across lines using the "\" as the last character
+on a line.  The maximum number of characters printed per line is 70.
+Due to the interactive nature of @command{bc}, printing a number causes
+the side effect of assigning the printed value to the special variable
+@var{last}. This allows the user to recover the last value printed
+without having to retype the expression that printed the number.
+Assigning to @var{last} is legal and will overwrite the last printed
+value with the assigned value.  The newly assigned value will remain
+until the next number is printed or another value is assigned to
+@var{last}.  (Some installations may allow the use of a single period
+(.) which is not part of a number as a short hand notation for for
+@var{last}.)
+
+@item string
+The string is printed to the output.  Strings start with a double quote
+character and contain all characters until the next double quote character.
+All characters are taken literally, including any newline.  No newline
+character is printed after the string.
+
+@item @code{print} @var{list}
+The @code{print} statement (an extension) provides another method of
+output.  The @var{list} is a list of strings and expressions separated by
+commas.  Each string or expression is printed in the order of the list.
+No terminating newline is printed.  Expressions are evaluated and their
+value is printed and assigned to the variable @code{last}. Strings in
+the print statement are printed to the output and may contain special
+characters.  Special characters start with the backslash character (\e).
+The special characters recognized by @command{bc} are "a" (alert or
+bell), "b" (backspace), "f" (form feed), "n" (newline), "r" (carriage
+return), "q" (double quote), "t" (tab), and "\e" (backslash).  Any other
+character following the backslash will be ignored.
+
+@item @{ statement_list @}
+This is the compound statement.  It allows multiple statements to be
+grouped together for execution.
+
+@item @code{if} ( expression ) statement1 [@code{else} statement2]
+The if statement evaluates the expression and executes statement1 or
+statement2 depending on the value of the expression.  If the expression
+is non-zero, statement1 is executed.  If statement2 is present and
+the value of the expression is 0, then statement2 is executed.  (The
+@code{else} clause is an extension.)
+
+@item @code{while} ( expression ) statement
+The while statement will execute the statement while the expression
+is non-zero.  It evaluates the expression before each execution of
+the statement.   Termination of the loop is caused by a zero
+expression value or the execution of a @code{break} statement.
+
+@item @code{for} ( [expression1] ; [expression2] ; [expression3] ) statement
+The @code{for} statement controls repeated execution of the statement.
+@var{Expression1} is evaluated before the loop.  @var{Expression2} is
+evaluated before each execution of the statement.  If it is non-zero,
+the statement is evaluated.  If it is zero, the loop is terminated.
+After each execution of the statement, @var{expression3} is evaluated
+before the reevaluation of expression2.  If @var{expression1} or
+@var{expression3} are missing, nothing is evaluated at the point they
+would be evaluated.  If @var{expression2} is missing, it is the same as
+substituting the value 1 for @var{expression2}.  (The optional
+expressions are an extension. POSIX @command{bc} requires all three
+expressions.)  The following is equivalent code for the @code{for}
+statement:
+
+@example
+expression1;
+while (expression2) @{
+   statement;
+   expression3;
+@}
+@end example
+
+@item @code{break}
+This statement causes a forced exit of the most recent enclosing @code{while}
+statement or @code{for} statement.
+
+@item @code{continue}
+The @code{continue} statement (an extension)  causes the most recent enclosing
+@code{for} statement to start the next iteration.
+
+@item @code{halt}
+The @code{halt} statement (an extension) is an executed statement that
+causes the @command{bc} processor to quit only when it is executed.  For
+example, "if (0 == 1) halt" will not cause @command{bc} to terminate
+because the @code{halt} is not executed.
+
+@item @code{return}
+Return the value 0 from a function.  (@xref{Functions}.)
+
+@item @code{return} ( expression )
+Return the value of the expression from a function.  (@xref{Functions}.)
+As an extension, the parenthesis are not required.
+@end table
+
+@node Pseudo Statements, , Statements, Statements
+@section Pseudo Statements
+
+These statements are not statements in the traditional sense.  They are
+not executed statements.  Their function is performed at "compile" time.
+
+@table @code
+@item limits
+Print the local limits enforced by the local version of @command{bc}.  This
+is an extension.
+
+@item quit
+When the @code{quit} statement is read, the @command{bc} processor
+is terminated, regardless of where the @code{quit} statement is found.  For
+example, "if (0 == 1) quit" will cause @command{bc} to terminate.
+
+@item warranty
+Print a longer warranty notice.  This is an extension.
+@end table
+
+@node Functions, Examples, Statements, Top
+@chapter Functions
+
+@menu
+* Math Library Functions::
+@end menu
+
+Functions provide a method of defining a computation that can be
+executed later.  Functions in @command{bc} always compute a value and
+return it to the caller.  Function definitions are "dynamic" in the
+sense that a function is undefined until a definition is encountered in
+the input.  That definition is then used until another definition
+function for the same name is encountered.  The new definition then
+replaces the older definition.  A function is defined as follows:
+
+@example
+@code{define} @var{name} @code{(} @var{parameters} @code{)} @code{@{} @var{newline}
+    @var{auto_list   statement_list} @code{@}}
+@end example
+
+A function call is just an expression of the form
+"@code{name} @code{(}@var{parameters}@code{)}".
+
+Parameters are numbers or arrays (an extension).  In the function definition,
+zero or more parameters are defined by listing their names separated by
+commas.  Numbers are only call by value parameters.  Arrays are only
+call by variable.  Arrays are specified in the parameter definition by
+the notation "@var{name}@code{[ ]}".   In the function call, actual parameters
+are full expressions for number parameters.  The same notation is used
+for passing arrays as for defining array parameters.  The named array is
+passed by variable to the function.  Since function definitions are dynamic,
+parameter numbers and types are checked when a function is called.  Any
+mismatch in number or types of parameters will cause a runtime error.
+A runtime error will also occur for the call to an undefined function.
+
+The @var{auto_list} is an optional list of variables that are for
+"local" use.  The syntax of the auto list (if present) is "@code{auto}
+@var{name}, ... ;".  (The semicolon is optional.)  Each @var{name} is
+the name of an auto variable.  Arrays may be specified by using the
+same notation as used in parameters.  These variables have their
+values pushed onto a stack at the start of the function.  The
+variables are then initialized to zero and used throughout the
+execution of the function.  At function exit, these variables are
+popped so that the original value (at the time of the function call)
+of these variables are restored.  The parameters are really auto
+variables that are initialized to a value provided in the function
+call.  
+Auto variables are different than traditional local variables
+because if function A calls function B, B may access function
+A's auto variables by just using the same name, unless function B has
+called them auto variables.  Due to the fact that auto variables and
+parameters are pushed onto a stack, @command{bc} supports recursive functions.
+
+The function body is a list of @command{bc} statements.  Again, statements
+are separated by semicolons or newlines.  Return statements cause the
+termination of a function and the return of a value.  There are two
+versions of the return statement.  The first form, "@code{return}", returns
+the value 0 to the calling expression.  The second form, 
+"@code{return} ( @var{expression} )", computes the value of the expression
+and returns that value to the calling expression.  There is an implied
+"@code{return} (0)" at the end of every function.  This allows a function
+to terminate and return 0 without an explicit @code{return} statement.
+
+Functions also change the usage of the variable @var{ibase}.  All
+constants in the function body will be converted using the value of
+@var{ibase} at the time of the function call.  Changes of @var{ibase}
+will be ignored during the execution of the function except for the
+standard function @code{read}, which will always use the current value
+of @var{ibase} for conversion of numbers.
+
+As an extension, the format of the definition has been slightly relaxed.
+The standard requires the opening brace be on the same line as the 
+@code{define} keyword and all other parts must be on following lines.
+This version of @command{bc} will allow any number of newlines before and
+after the opening brace of the function.  For example, the following
+definitions are legal.
+
+@example
+   define d (n) @{ return (2*n); @}
+   define d (n)
+       @{ return (2*n); @}
+@end example
+
+
+@node Math Library Functions, , Functions, Functions
+@section Math Library Functions
+
+If @command{bc} is invoked with the @code{-l} option, a math library is
+preloaded and the default @var{scale} is set to 20.  The math functions will
+calculate their results to the scale set at the time of their call.  The
+math library defines the following functions:
+
+@table @code
+@item s (@var{x})
+The sine of @var{x}, @var{x} is in radians.
+
+@item c (@var{x})
+The cosine of @var{x}, @var{x} is in radians.
+
+@item a (@var{x})
+The arctangent of @var{x}, arctangent returns radians.
+
+@item l (@var{x})
+The natural logarithm of @var{x}.
+
+@item @var{e} (@var{x})
+The exponential function of raising @var{e} to the value @var{x}.
+
+@item @var{j} (@var{n,x})
+The bessel function of integer order @var{n} of @var{x}.
+@end table
+
+@node Examples, Readline and Libedit Options, Functions, Top
+@chapter Examples
+
+In /bin/sh,  the following will assign the value of "pi" to the shell
+variable @var{pi}.
+@example
+
+pi=$(echo "scale=10; 4*a(1)" | bc -l)
+
+@end example
+
+The following is the definition of the exponential function used in the
+math library.  This function is written in POSIX @command{bc}.
+
+@example
+
+scale = 20
+
+/* Uses the fact that e^x = (e^(x/2))^2
+   When x is small enough, we use the series:
+     e^x = 1 + x + x^2/2! + x^3/3! + ...
+*/
+
+define e(x) @{
+  auto  a, d, e, f, i, m, v, z
+
+  /* Check the sign of x. */
+  if (x<0) @{
+    m = 1
+    x = -x
+  @} 
+
+  /* Precondition x. */
+  z = scale;
+  scale = 4 + z + .44*x;
+  while (x > 1) @{
+    f += 1;
+    x /= 2;
+  @}
+
+  /* Initialize the variables. */
+  v = 1+x
+  a = x
+  d = 1
+
+  for (i=2; 1; i++) @{
+    e = (a *= x) / (d *= i)
+    if (e == 0) @{
+      if (f>0) while (f--)  v = v*v;
+      scale = z
+      if (m) return (1/v);
+      return (v/1);
+    @}
+    v += e
+  @}
+@}
+
+@end example
+
+The following is code that uses the extended features of @command{bc} to
+implement a simple program for calculating checkbook balances.  This
+program is best kept in a file so that it can be used many times 
+without having to retype it at every use.
+
+@example
+
+scale=2
+print "\nCheck book program\n!"
+print "  Remember, deposits are negative transactions.\n"
+print "  Exit by a 0 transaction.\n\n"
+
+print "Initial balance? "; bal = read()
+bal /= 1
+print "\n"
+while (1) @{
+  "current balance = "; bal
+  "transaction? "; trans = read()
+  if (trans == 0) break;
+  bal -= trans
+  bal /= 1
+@}
+quit
+
+@end example
+
+
+The following is the definition of the recursive factorial function.
+
+@example
+
+define f (x) @{
+  if (x <= 1) return (1);
+  return (f(x-1) * x);
+@}
+
+@end example
+
+@node Readline and Libedit Options, GNU @command{bc} and Other Implementations, Examples, Top
+@chapter Readline and Libedit Options
+
+GNU @command{bc} can be compiled (via a configure option) to use the GNU
+@command{readline} input editor library or the BSD @command{libedit}
+library.  This allows the user to do
+more editing of lines before sending them to @command{bc}.  It also
+allows for a history of previous lines typed.  When this option is
+selected, @command{bc} has one more special variable.  This special
+variable, @var{history} is the number of lines of history retained.  A
+value of -1 means that an unlimited number of history lines are
+retained.  This is the default value.  Setting the value of
+@var{history} to a positive number restricts the number of history lines
+to the number given.  The value of 0 disables the history feature.  For
+more information, read the user manuals for the GNU @command{readline},
+@command{history} and BSD @command{libedit} libraries.  One can not
+enable both @command{readline} and @command{libedit} at the same time.
+
+@node GNU @command{bc} and Other Implementations, Limits, Readline and Libedit Options, Top
+@chapter GNU @command{bc} and Other Implementations
+
+This version of @command{bc} was implemented from the POSIX P1003.2/D11
+draft and contains several differences and extensions relative to the
+draft and traditional implementations.  It is not implemented in the
+traditional way using @command{dc}.  This version is a single process
+which parses and runs a byte code translation of the program.  There is
+an "undocumented" option (-c) that causes the program to output the byte
+code to the standard output instead of running it.  It was mainly used
+for debugging the parser and preparing the math library.
+
+A major source of differences is extensions, where a feature is extended
+to add more functionality and additions, where new features are added.
+The following is the list of differences and extensions.
+
+@table @var
+
+@item LANG environment
+This version does not conform to the POSIX standard in the processing
+of the LANG environment variable and all environment variables starting
+with LC_.
+
+@item names
+Traditional and POSIX @command{bc}
+have single letter names for functions, variables and arrays.  They have
+been extended to be multi-character names that start with a letter and
+may contain letters, numbers and the underscore character.
+
+@item Strings
+Strings are not allowed to contain NUL characters.  POSIX says all characters
+must be included in strings.
+
+@item last
+POSIX @command{bc} does not have a \fBlast variable.  Some implementations
+of @command{bc} use the period (.) in a similar way.  
+
+@item comparisons
+POSIX @command{bc} allows comparisons only in the @code{if} statement,
+the @code{while} statement, and the second expression of the @code{for}
+statement.  Also, only one relational operation is allowed in each of
+those statements.
+
+@item if statement, else clause
+POSIX @command{bc} does not have an @code{else} clause.
+
+@item for statement
+POSIX @command{bc} requires all expressions to be present in the
+@code{for} statement.
+
+@item &&, ||, !
+POSIX @command{bc} does not have the logical operators.
+
+@item read function
+POSIX @command{bc} does not have a @code{read} function.
+
+@item print statement
+POSIX @command{bc} does not have a @code{print} statement.
+
+@item continue statement
+POSIX @command{bc} does not have a continue statement.
+
+@item array parameters
+POSIX @command{bc} does not (currently) support array parameters in full.
+The POSIX grammar allows for arrays in function definitions, but does
+not provide a method to specify an array as an actual parameter.  (This
+is most likely an oversight in the grammar.)  Traditional implementations
+of @command{bc} have only call by value array parameters.
+
+@item function format
+POSIX @command{bc} requires the opening brace on the same line as the 
+@code{define} key word and the @code{auto} statement on the next line.
+
+@item =+, =-, =*, =/, =%, =^
+POSIX @command{bc} does not require these "old style" assignment
+operators to be defined.  This version may allow these "old style"
+assignments.  Use the @code{limits} statement to see if the installed
+version supports them.  If it does support the "old style" assignment
+operators, the statement "a =- 1" will decrement @code{a} by 1 instead
+of setting @code{a} to the value -1.
+
+@item spaces in numbers
+Other implementations of @command{bc} allow spaces in numbers.  For example,
+"x=1 3" would assign the value 13 to the variable x.  The same statement
+would cause a syntax error in this version of @command{bc}.
+
+@item errors and execution
+This implementation varies from other implementations in terms of what
+code will be executed when syntax and other errors are found in the
+program.  If a syntax error is found in a function definition, error
+recovery tries to find the beginning of a statement and continue to
+parse the function.  Once a syntax error is found in the function, the
+function will not be callable and becomes undefined.
+Syntax errors in the interactive execution code will invalidate the
+current execution block.  The execution block is terminated by an
+end of line that appears after a complete sequence of statements.
+For example, 
+
+@example
+a = 1
+b = 2
+@end example
+
+has two execution blocks and
+
+@example
+@{ a = 1
+  b = 2 @}
+@end example
+
+has one execution block.  Any runtime error will terminate the execution
+of the current execution block.  A runtime warning will not terminate the
+current execution block.
+
+@item Interrupts
+During an interactive session, the SIGINT signal (usually generated by
+the control-C character from the terminal) will cause execution of the
+current execution block to be interrupted.  It will display a "runtime"
+error indicating which function was interrupted.  After all runtime
+structures have been cleaned up, a message will be printed to notify the
+user that @command{bc} is ready for more input.  All previously defined
+functions remain defined and the value of all non-auto variables are the
+value at the point of interruption.  All auto variables and function
+parameters are removed during the clean up process.  During a
+non-interactive session, the SIGINT signal will terminate the entire run
+of @command{bc}.
+@end table
+
+@node Limits, Environment Variables, GNU @command{bc} and Other Implementations, Top
+@chapter Limits
+
+The following are the limits currently in place for this @command{bc}
+processor.  Some of them may have been changed by an installation.  Use
+the @code{limits} statement to see the actual values.
+
+@table @code
+
+@item BC_BASE_MAX
+The maximum output base is currently set at 999.  The maximum input base
+is 16.
+
+@item BC_DIM_MAX
+This is currently an arbitrary limit of 65535 as distributed.  Your
+installation may be different.
+
+@item BC_SCALE_MAX
+The number of digits after the decimal point is limited to INT_MAX digits.
+Also, the number of digits before the decimal point is limited to INT_MAX
+digits.
+
+@item BC_STRING_MAX
+The limit on the number of characters in a string is INT_MAX characters.
+
+@item exponent
+The value of the exponent in the raise operation (^) is limited to LONG_MAX.
+
+@item multiply
+The multiply routine may yield incorrect results if a number
+has more than LONG_MAX / 90 total digits.  For 32 bit longs, this number is
+23,860,929 digits.
+
+@item variable names
+The current limit on the number of unique names is 32767 for each of
+simple variables, arrays and functions.
+@end table
+
+@node Environment Variables, , Limits, Top
+@chapter Environment Variables
+
+The following environment variables are processed by @command{bc}:
+
+@table @code
+
+
+@item POSIXLY_CORRECT
+This is the same as the -s option (@pxref{Command Line Options}).
+
+@item BC_ENV_ARGS
+This is another mechanism to get arguments to @command{bc}.  The format
+is the same as the command line arguments.  These arguments are
+processed first, so any files listed in the environent arguments are
+processed before any command line argument files.  This allows the user
+to set up "standard" options and files to be processed at every
+invocation of @command{bc}.  The files in the environment variables
+would typically contain function definitions for functions the user
+wants defined every time @command{bc} is run.
+
+@item BC_LINE_LENGTH
+This should be an integer specifing the number of characters in an
+output line for numbers. This includes the backslash and newline
+characters for long numbers.
+@end table
+
+@contents
+@bye
+
+
diff --git a/doc/dc.1 b/doc/dc.1
new file mode 100644 (file)
index 0000000..7a136a7
--- /dev/null
+++ b/doc/dc.1
@@ -0,0 +1,488 @@
+.\"
+.\" dc.1 - the *roff document processor source for the dc manual
+.\"
+.\" This file is part of GNU dc.
+.\" Copyright (C) 1994, 1997, 1998, 2000 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 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; see the file COPYING.  If not, write to:
+.\"   The Free Software Foundation, Inc.
+.\"   59 Temple Place, Suite 330
+.\"   Boston, MA 02111 USA
+.\"
+.TH DC 1 "1997-03-25" "GNU Project"
+.ds dc \fIdc\fP
+.ds Dc \fIDc\fP
+.SH NAME
+dc \- an arbitrary precision calculator
+.SH SYNOPSIS
+dc [-V] [--version] [-h] [--help]
+   [-e scriptexpression] [--expression=scriptexpression]
+   [-f scriptfile] [--file=scriptfile]
+   [file ...]
+.SH DESCRIPTION
+.PP
+\*(Dc is a reverse-polish desk calculator which supports
+unlimited precision arithmetic.
+It also allows you to define and call macros.
+Normally \*(dc reads from the standard input;
+if any command arguments are given to it, they are filenames,
+and \*(dc reads and executes the contents of the files before reading
+from standard input.
+All normal output is to standard output;
+all error output is to standard error.
+.PP
+A reverse-polish calculator stores numbers on a stack.
+Entering a number pushes it on the stack.
+Arithmetic operations pop arguments off the stack and push the results.
+.PP
+To enter a number in
+.IR dc ,
+type the digits with an optional decimal point.
+Exponential notation is not supported.
+To enter a negative number,
+begin the number with ``_''.
+``-'' cannot be used for this,
+as it is a binary operator for subtraction instead.
+To enter two numbers in succession,
+separate them with spaces or newlines.
+These have no meaning as commands.
+.SH OPTIONS
+\*(Dc may be invoked with the following command-line options:
+.TP
+.B -V
+.TP
+.B --version
+Print out the version of \*(dc that is being run and a copyright notice,
+then exit.
+.TP
+.B -h
+.TP
+.B --help
+Print a usage message briefly summarizing these command-line options
+and the bug-reporting address,
+then exit.
+.TP
+.B -e \fIscript\fP
+.TP
+.BI --expression= script
+Add the commands in
+.I script
+to the set of commands to be run while processing the input.
+.TP
+.B -f \fIscript-file\fP
+.TP
+.BI --file= script-file
+Add the commands contained in the file
+.I script-file
+to the set of commands to be run while processing the input.
+.PP
+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
+.B -
+refers to the standard input stream.
+The standard input will processed if no file names are specified.
+.PD
+.SH
+Printing Commands
+.TP
+.B p
+Prints the value on the top of the stack,
+without altering the stack.
+A newline is printed after the value.
+.TP
+.B n
+Prints the value on the top of the stack, popping it off,
+and does not print a newline after.
+.TP
+.B P
+Pops off the value on top of the stack.
+If it it a string, it is simply printed without a trailing newline.
+Otherwise it is a number, and the integer portion of its absolute
+value is printed out as a "base (UCHAR_MAX+1)" byte stream.
+Assuming that (UCHAR_MAX+1) is 256
+(as it is on most machines with 8-bit bytes),
+the sequence \fBKSK 0k1/ [_1*]sx d0>x [256~aPd0<x]dsxx sxLKk\fP
+could also accomplish this function,
+except for the side-effect of clobbering the x register.
+.TP
+.B f
+Prints the entire contents of the stack
+.ig
+and the contents of all of the registers,
+..
+without altering anything.
+This is a good command to use if you are lost or want
+to figure out what the effect of some command has been.
+.PD
+.SH
+Arithmetic
+.TP
+.B +
+Pops two values off the stack, adds them,
+and pushes the result.
+The precision of the result is determined only
+by the values of the arguments,
+and is enough to be exact.
+.TP
+.B -
+Pops two values,
+subtracts the first one popped from the second one popped,
+and pushes the result.
+.TP
+.B *
+Pops two values, multiplies them, and pushes the result.
+The number of fraction digits in the result depends on
+the current precision value and the number of fraction
+digits in the two arguments.
+.TP
+.B /
+Pops two values,
+divides the second one popped from the first one popped,
+and pushes the result.
+The number of fraction digits is specified by the precision value.
+.TP
+.B %
+Pops two values,
+computes the remainder of the division that the
+.B /
+command would do,
+and pushes that.
+The value computed is the same as that computed by
+the sequence \fBSd dld/ Ld*-\fP .
+.TP
+.B ~
+Pops two values,
+divides the second one popped from the first one popped.
+The quotient is pushed first, and the remainder is pushed next.
+The number of fraction digits used in the division
+is specified by the precision value.
+(The sequence \fBSdSn lnld/ LnLd%\fP could also accomplish
+this function, with slightly different error checking.)
+.TP
+.B ^
+Pops two values and exponentiates,
+using the first value popped as the exponent
+and the second popped as the base.
+The fraction part of the exponent is ignored.
+The precision value specifies the number of fraction
+digits in the result.
+.TP
+.B |
+Pops three values and computes a modular exponentiation.
+The first value popped is used as the reduction modulus;
+this value must be a non-zero number,
+and should be an integer.
+The second popped is used as the exponent;
+this value must be a non-negative number,
+and any fractional part of this exponent will be ignored.
+The third value popped is the base which gets exponentiated,
+which should be an integer.
+For small integers this is like the sequence \fBSm^Lm%\fP,
+but, unlike \fB^\fP, this command will work with arbitrarily large exponents.
+.TP
+.B v
+Pops one value,
+computes its square root,
+and pushes that.
+The precision value specifies the number of fraction digits in the result.
+.PP
+Most arithmetic operations are affected by the ``precision value'',
+which you can set with the
+.B k
+command.
+The default precision value is zero,
+which means that all arithmetic except for
+addition and subtraction produces integer results.
+.SH
+Stack Control
+.TP
+.B c
+Clears the stack, rendering it empty.
+.TP
+.B d
+Duplicates the value on the top of the stack,
+pushing another copy of it.
+Thus, ``4d*p'' computes 4 squared and prints it.
+.TP
+.B r
+Reverses the order of (swaps) the top two values on the stack.
+.SH
+Registers
+.PP
+\*(Dc provides at least 256 memory registers,
+each named by a single character.
+You can store a number or a string in a register and retrieve it later.
+.TP
+.BI s r
+Pop the value off the top of the stack and store
+it into register
+.IR r .
+.TP
+.BI l r
+Copy the value in register
+.I r
+and push it onto the stack.
+This does not alter the contents of
+.IR r .
+.PP
+Each register also contains its own stack.
+The current register value is the top of the register's stack.
+.TP
+.BI S r
+Pop the value off the top of the (main) stack and
+push it onto the stack of register
+.IR r .
+The previous value of the register becomes inaccessible.
+.TP
+.BI L r
+Pop the value off the top of register
+.IR r 's
+stack and push it onto the main stack.
+The previous value
+in register
+.IR r 's
+stack, if any,
+is now accessible via the
+.BI l r
+command.
+.ig
+.PP
+The
+.B f
+command prints a list of all registers that have contents stored in them,
+together with their contents.
+Only the current contents of each register
+(the top of its stack)
+is printed.
+..
+.SH
+Parameters
+.PP
+\*(Dc has three parameters that control its operation:
+the precision, the input radix, and the output radix.
+The precision specifies the number
+of fraction digits to keep in the result of most arithmetic operations.
+The input radix controls the interpretation of numbers typed in;
+all numbers typed in use this radix.
+The output radix is used for printing numbers.
+.PP
+The input and output radices are separate parameters;
+you can make them unequal,
+which can be useful or confusing.
+The input radix must be between 2 and 16 inclusive.
+The output radix must be at least 2.
+The precision must be zero or greater.
+The precision is always measured in decimal digits,
+regardless of the current input or output radix.
+.TP
+.B i
+Pops the value off the top of the stack
+and uses it to set the input radix.
+.TP
+.B o
+Pops the value off the top of the stack
+and uses it to set the output radix.
+.TP
+.B k
+Pops the value off the top of the stack
+and uses it to set the precision.
+.TP
+.B I
+Pushes the current input radix on the stack.
+.TP
+.B O
+Pushes the current output radix on the stack.
+.TP
+.B K
+Pushes the current precision on the stack.
+.SH
+Strings
+.PP
+\*(Dc can operate on strings as well as on numbers.
+The only things you can do with strings are
+print them and execute them as macros
+(which means that the contents of the string are processed as
+\*(dc commands).
+All registers and the stack can hold strings,
+and \*(dc always knows whether any given object is a string or a number.
+Some commands such as arithmetic operations demand numbers
+as arguments and print errors if given strings.
+Other commands can accept either a number or a string;
+for example, the
+.B p
+command can accept either and prints the object
+according to its type.
+.TP
+.BI [ characters ]
+Makes a string containing
+.I characters
+(contained between balanced
+.B [
+and
+.B ]
+characters),
+and pushes it on the stack.
+For example,
+.B [foo]P
+prints the characters
+.B foo
+(with no newline).
+.TP
+.B a
+The top-of-stack is popped.
+If it was a number, then the low-order byte of this number
+is converted into a string and pushed onto the stack.
+Otherwise the top-of-stack was a string,
+and the first character of that string is pushed back.
+.TP
+.B x
+Pops a value off the stack and executes it as a macro.
+Normally it should be a string;
+if it is a number,
+it is simply pushed back onto the stack.
+For example,
+.B [1p]x
+executes the macro
+.B 1p
+which pushes
+.B 1
+on the stack and prints
+.B 1
+on a separate line.
+.PP
+Macros are most often stored in registers;
+.B [1p]sa
+stores a macro to print
+.B 1
+into register
+.BR a ,
+and
+.B lax
+invokes this macro.
+.TP
+.BI > r
+Pops two values off the stack and compares them
+assuming they are numbers,
+executing the contents of register
+.I r
+as a macro if the original top-of-stack
+is greater.
+Thus,
+.B 1 2>a
+will invoke register
+.BR a 's
+contents and
+.B 2 1>a
+will not.
+.TP
+.BI !> r
+Similar but invokes the macro if the original top-of-stack is
+not greater than (less than or equal to) what was the second-to-top.
+.TP
+.BI < r
+Similar but invokes the macro if the original top-of-stack is less.
+.TP
+.BI !< r
+Similar but invokes the macro if the original top-of-stack is
+not less than (greater than or equal to) what was the second-to-top.
+.TP
+.BI = r
+Similar but invokes the macro if the two numbers popped are equal.
+.TP
+.BI != r
+Similar but invokes the macro if the two numbers popped are not equal.
+.ig
+This can also be validly used to compare two strings for equality.
+..
+.TP
+.B ?
+Reads a line from the terminal and executes it.
+This command allows a macro to request input from the user.
+.TP
+.B q
+exits from a macro and also from the macro which invoked it.
+If called from the top level,
+or from a macro which was called directly from the top level,
+the
+.B q
+command will cause \*(dc to exit.
+.TP
+.B Q
+Pops a value off the stack and uses it as a count
+of levels of macro execution to be exited.
+Thus,
+.B 3Q
+exits three levels.
+The
+.B Q
+command will never cause \*(dc to exit.
+.SH
+Status Inquiry
+.TP
+.B Z
+Pops a value off the stack,
+calculates the number of digits it has
+(or number of characters, if it is a string)
+and pushes that number.
+.TP
+.B X
+Pops a value off the stack,
+calculates the number of fraction digits it has,
+and pushes that number.
+For a string,
+the value pushed is
+.\" -1.
+0.
+.TP
+.B z
+Pushes the current stack depth:
+the number of objects on the stack before the execution of the
+.B z
+command.
+.SH
+Miscellaneous
+.TP
+.B !
+Will run the rest of the line as a system command.
+Note that parsing of the !<, !=, and !> commands take precedence,
+so if you want to run a command starting with <, =, or > you will
+need to add a space after the !.
+.TP
+.B #
+Will interpret the rest of the line as a comment.
+.TP
+.BI : r
+Will pop the top two values off of the stack.
+The old second-to-top value will be stored in the array
+.IR r ,
+indexed by the old top-of-stack value.
+.TP
+.BI ; r
+Pops the top-of-stack and uses it as an index into
+the array
+.IR r .
+The selected value is then pushed onto the stack.
+.P
+Note that each stacked instance of a register has its own
+array associated with it.
+Thus \fB1 0:a 0Sa 2 0:a La 0;ap\fP will print 1,
+because the 2 was stored in an instance of 0:a that
+was later popped.
+.SH
+BUGS
+.PP
+Email bug reports to
+.BR bug-dc@gnu.org .
diff --git a/doc/dc.info b/doc/dc.info
new file mode 100644 (file)
index 0000000..050a6b3
--- /dev/null
@@ -0,0 +1,441 @@
+This is dc.info, produced by makeinfo version 4.0 from dc.texi.
+
+START-INFO-DIR-ENTRY
+* dc: (dc).                   Arbritrary precision RPN "Desktop Calculator".
+END-INFO-DIR-ENTRY
+   This file documents DC, an arbitrary precision calculator.
+
+   Published by the Free Software Foundation, Inc.  59 Temple Place,
+Suite 330 Boston, MA 02111 USA
+
+   Copyright (C) 1984, 1994, 1997, 1998, 2000 Free Software Foundation,
+Inc.
+
+   Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+   Permission is granted to copy and distribute modified versions of
+this manual under the conditions for verbatim copying, provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+   Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the Foundation.
+
+\1f
+File: dc.info,  Node: Top,  Next: Introduction,  Prev: (dir),  Up: (dir)
+
+* Menu:
+
+* Introduction::                Introduction
+* Invocation::                  Invocation
+* Printing Commands::           Printing Commands
+* Arithmetic::                  Arithmetic
+* Stack Control::               Stack Control
+* Registers::                   Registers
+* Parameters::                  Parameters
+* Strings::                     Strings
+* Status Inquiry::              Status Inquiry
+* Miscellaneous::               Other commands
+* Reporting bugs::              Reporting bugs
+
+\1f
+File: dc.info,  Node: Introduction,  Next: Invocation,  Prev: Top,  Up: Top
+
+Introduction
+************
+
+   DC is a reverse-polish desk calculator which supports unlimited
+precision arithmetic.  It also allows you to define and call macros.
+Normally DC reads from the standard input; if any command arguments are
+given to it, they are filenames, and DC reads and executes the contents
+of the files instead of reading from standard input.  All normal output
+is to standard output; all error messages are written to standard error.
+
+   To exit, use `q'.  `C-c' does not exit; it is used to abort macros
+that are looping, etc.  (Currently this is not true; `C-c' does exit.)
+
+   A reverse-polish calculator stores numbers on a stack.  Entering a
+number pushes it on the stack.  Arithmetic operations pop arguments off
+the stack and push the results.
+
+   To enter a number in DC, type the digits, with an optional decimal
+point.  Exponential notation is not supported.  To enter a negative
+number, begin the number with `_'.  `-' cannot be used for this, as it
+is a binary operator for subtraction instead.  To enter two numbers in
+succession, separate them with spaces or newlines.  These have no
+meaning as commands.
+
+\1f
+File: dc.info,  Node: Invocation,  Next: Printing Commands,  Prev: Introduction,  Up: Top
+
+Invocation
+**********
+
+   DC may be invoked with the following command-line options:
+`-e EXPR'
+
+`--expression=EXPR'
+     Evaluate EXPR as DC commands.
+
+`-f FILE'
+
+`--file=FILE'
+     Read and evaluate DC commands from FILE.
+
+`-h'
+
+`--help'
+     Print a usage message summarizing the command-line options, then
+     exit.
+
+`-V'
+
+`--version'
+     Print the version information for this program, then exit.
+
+   If any command-line parameters remain after processing the options,
+these parameters are interpreted as additional FILEs whose contents are
+read and evaluated.  A file name of `-' refers to the standard input
+stream.  If no `-e' option was specified, and no files were specified,
+then the standard input will be read for commands to evaluate.
+
+\1f
+File: dc.info,  Node: Printing Commands,  Next: Arithmetic,  Prev: Invocation,  Up: Top
+
+Printing Commands
+*****************
+
+`p'
+     Prints the value on the top of the stack, without altering the
+     stack.  A newline is printed after the value.
+
+`n'
+     Prints the value on the top of the stack, popping it off, and does
+     not print a newline after.  (This command is a GNU extension.)
+
+`P'
+     Pops off the value on top of the stack.  If it it a string, it is
+     simply printed without a trailing newline.  Otherwise it is a
+     number, and the integer portion of its absolute value is printed
+     out as a "base (UCHAR_MAX+1)" byte stream.  Assuming that
+     (UCHAR_MAX+1) is 256 (as it is on most machines with 8-bit bytes),
+     the sequence `KSK 0k1/ [_1*]sx d0>x [256~aPd0<x]dsxx sxLKk' could
+     also accomplish this function, except for the side-effect of
+     clobbering the x register.  (Details of the behavior with a number
+     are a GNU extension.)
+
+`f'
+     Prints the entire contents of the stack without altering anything.
+     This is a good command to use if you are lost or want to figure
+     out what the effect of some command has been.
+
+\1f
+File: dc.info,  Node: Arithmetic,  Next: Stack Control,  Prev: Printing Commands,  Up: Top
+
+Arithmetic
+**********
+
+`+'
+     Pops two values off the stack, adds them, and pushes the result.
+     The precision of the result is determined only by the values of
+     the arguments, and is enough to be exact.
+
+`-'
+     Pops two values, subtracts the first one popped from the second
+     one popped, and pushes the result.
+
+`*'
+     Pops two values, multiplies them, and pushes the result.  The
+     number of fraction digits in the result is the largest of the
+     precision value, the number of fraction digits in the multiplier,
+     or the number of fraction digits in the multiplicand; but in no
+     event exceeding the number of digits required for an exact result.
+
+`/'
+     Pops two values, divides the second one popped from the first one
+     popped, and pushes the result.  The number of fraction digits is
+     specified by the precision value.
+
+`%'
+     Pops two values, computes the remainder of the division that the
+     `/' command would do, and pushes that.  The value computed is the
+     same as that computed by the sequence `Sd dld/ Ld*-' .
+
+`~'
+     Pops two values, divides the second one popped from the first one
+     popped.  The quotient is pushed first, and the remainder is pushed
+     next.  The number of fraction digits used in the division is
+     specified by the precision value.  (The sequence `SdSn lnld/
+     LnLd%' could also accomplish this function, with slightly
+     different error checking.)  (This command is a GNU extension.)
+
+`^'
+     Pops two values and exponentiates, using the first value popped as
+     the exponent and the second popped as the base.  The fraction part
+     of the exponent is ignored.  The precision value specifies the
+     number of fraction digits in the result.
+
+`|'
+     Pops three values and computes a modular exponentiation.  The
+     first value popped is used as the reduction modulus; this value
+     must be a non-zero number, and the result may not be accurate if
+     the modulus is not an integer.  The second popped is used as the
+     exponent; this value must be a non-negative number, and any
+     fractional part of this exponent will be ignored.  The third value
+     popped is the base which gets exponentiated, which should be an
+     integer.  For small integers this is like the sequence `Sm^Lm%',
+     but, unlike `^', this command will work with arbritrarily large
+     exponents.  (This command is a GNU extension.)
+
+`v'
+     Pops one value, computes its square root, and pushes that.  The
+     precision value specifies the number of fraction digits in the
+     result.
+
+   Most arithmetic operations are affected by the _precision value_,
+which you can set with the `k' command.  The default precision value is
+zero, which means that all arithmetic except for addition and
+subtraction produces integer results.
+
+\1f
+File: dc.info,  Node: Stack Control,  Next: Registers,  Prev: Arithmetic,  Up: Top
+
+Stack Control
+*************
+
+`c'
+     Clears the stack, rendering it empty.
+
+`d'
+     Duplicates the value on the top of the stack, pushing another copy
+     of it.  Thus, `4d*p' computes 4 squared and prints it.
+
+`r'
+     Reverses the order of (swaps) the top two values on the stack.
+     (This command is a GNU extension.)
+
+\1f
+File: dc.info,  Node: Registers,  Next: Parameters,  Prev: Stack Control,  Up: Top
+
+Registers
+*********
+
+   DC provides at least 256 memory registers, each named by a single
+character.  You can store a number in a register and retrieve it later.
+
+`sR'
+     Pop the value off the top of the stack and store it into register
+     R.
+
+`lR'
+     Copy the value in register R, and push it onto the stack.  This
+     does not alter the contents of R.
+
+     Each register also contains its own stack.  The current register
+     value is the top of the register's stack.
+
+`SR'
+     Pop the value off the top of the (main) stack and push it onto the
+     stack of register R.  The previous value of the register becomes
+     inaccessible.
+
+`LR'
+     Pop the value off the top of register R's stack and push it onto
+     the main stack.  The previous value in register R's stack, if any,
+     is now accessible via the `lR' command.
+
+\1f
+File: dc.info,  Node: Parameters,  Next: Strings,  Prev: Registers,  Up: Top
+
+Parameters
+**********
+
+   DC has three parameters that control its operation: the precision,
+the input radix, and the output radix.  The precision specifies the
+number of fraction digits to keep in the result of most arithmetic
+operations.  The input radix controls the interpretation of numbers
+typed in; _all_ numbers typed in use this radix.  The output radix is
+used for printing numbers.
+
+   The input and output radices are separate parameters; you can make
+them unequal, which can be useful or confusing.  The input radix must
+be between 2 and 16 inclusive.  The output radix must be at least 2.
+The precision must be zero or greater.  The precision is always
+measured in decimal digits, regardless of the current input or output
+radix.
+
+`i'
+     Pops the value off the top of the stack and uses it to set the
+     input radix.
+
+`o'
+     Pops the value off the top of the stack and uses it to set the
+     output radix.
+
+`k'
+     Pops the value off the top of the stack and uses it to set the
+     precision.
+
+`I'
+     Pushes the current input radix on the stack.
+
+`O'
+     Pushes the current output radix on the stack.
+
+`K'
+     Pushes the current precision on the stack.
+
+\1f
+File: dc.info,  Node: Strings,  Next: Status Inquiry,  Prev: Parameters,  Up: Top
+
+Strings
+*******
+
+   DC can operate on strings as well as on numbers.  The only things
+you can do with strings are print them and execute them as macros
+(which means that the contents of the string are processed as DC
+commands).  Both registers and the stack can hold strings, and DC
+always knows whether any given object is a string or a number.  Some
+commands such as arithmetic operations demand numbers as arguments and
+print errors if given strings.  Other commands can accept either a
+number or a string; for example, the `p' command can accept either and
+prints the object according to its type.
+
+`[CHARACTERS]'
+     Makes a string containing CHARACTERS and pushes it on the stack.
+     For example, `[foo]P' prints the characters `foo' (with no
+     newline).
+
+`a'
+     The mnemonic for this is somewhat erroneous: asciify.  The
+     top-of-stack is popped.  If it was a number, then the low-order
+     byte of this number is converted into a string and pushed onto the
+     stack.  Otherwise the top-of-stack was a string, and the first
+     character of that string is pushed back.  (This command is a GNU
+     extension.)
+
+`x'
+     Pops a value off the stack and executes it as a macro.  Normally
+     it should be a string; if it is a number, it is simply pushed back
+     onto the stack.  For example, `[1p]x' executes the macro `1p',
+     which pushes 1 on the stack and prints `1' on a separate line.
+
+     Macros are most often stored in registers; `[1p]sa' stores a macro
+     to print `1' into register `a', and `lax' invokes the macro.
+
+`>R'
+     Pops two values off the stack and compares them assuming they are
+     numbers, executing the contents of register R as a macro if the
+     original top-of-stack is greater.  Thus, `1 2>a' will invoke
+     register `a''s contents and `2 1>a' will not.
+
+`!>R'
+     Similar but invokes the macro if the original top-of-stack is not
+     greater (is less than or equal to) what was the second-to-top.
+
+`<R'
+     Similar but invokes the macro if the original top-of-stack is less.
+
+`!<R'
+     Similar but invokes the macro if the original top-of-stack is not
+     less (is greater than or equal to) what was the second-to-top.
+
+`=R'
+     Similar but invokes the macro if the two numbers popped are equal.
+
+`!=R'
+     Similar but invokes the macro if the two numbers popped are not
+     equal.
+
+`?'
+     Reads a line from the terminal and executes it.  This command
+     allows a macro to request input from the user.
+
+`q'
+     During the execution of a macro, this command exits from the macro
+     and also from the macro which invoked it.  If called from the top
+     level, or from a macro which was called directly from the top
+     level, the `q' command will cause DC to exit.
+
+`Q'
+     Pops a value off the stack and uses it as a count of levels of
+     macro execution to be exited.  Thus, `3Q' exits three levels.
+
+\1f
+File: dc.info,  Node: Status Inquiry,  Next: Miscellaneous,  Prev: Strings,  Up: Top
+
+Status Inquiry
+**************
+
+`Z'
+     Pops a value off the stack, calculates the number of digits it has
+     (or number of characters, if it is a string) and pushes that
+     number.
+
+`X'
+     Pops a value off the stack, calculates the number of fraction
+     digits it has, and pushes that number.  For a string, the value
+     pushed is 0.
+
+`z'
+     Pushes the current stack depth: the number of objects on the stack
+     before the execution of the `z' command.
+
+\1f
+File: dc.info,  Node: Miscellaneous,  Next: Reporting bugs,  Prev: Status Inquiry,  Up: Top
+
+Miscellaneous
+*************
+
+`!'
+     Will run the rest of the line as a system command.  Note that
+     parsing of the !<, !=, and !> commands take precidence, so if you
+     want to run a command starting with <, =, or > you will need to
+     add a space after the !.
+
+`#'
+     Will interpret the rest of the line as a comment.  (This command
+     is a GNU extension.)
+
+`:R'
+     Will pop the top two values off of the stack.  The old
+     second-to-top value will be stored in the array R, indexed by the
+     old top-of-stack value.
+
+`;R'
+     Pops the top-of-stack and uses it as an index into the array R.
+     The selected value is then pushed onto the stack.
+
+   Note that each stacked instance of a register has its own array
+associated with it.  Thus `1 0:A 0SA 2 0:A LA 0;Ap' will print 1,
+because the 2 was stored in an instance of 0:A that was later popped.
+
+\1f
+File: dc.info,  Node: Reporting bugs,  Prev: Miscellaneous,  Up: Top
+
+Reporting bugs
+**************
+
+   Email bug reports to <bug-dc@gnu.org>.
+
+
+\1f
+Tag Table:
+Node: Top\7f1084
+Node: Introduction\7f1663
+Node: Invocation\7f2880
+Node: Printing Commands\7f3724
+Node: Arithmetic\7f4902
+Node: Stack Control\7f7815
+Node: Registers\7f8228
+Node: Parameters\7f9154
+Node: Strings\7f10415
+Node: Status Inquiry\7f13385
+Node: Miscellaneous\7f13942
+Node: Reporting bugs\7f14909
+\1f
+End Tag Table
diff --git a/doc/dc.texi b/doc/dc.texi
new file mode 100644 (file)
index 0000000..0a4d973
--- /dev/null
@@ -0,0 +1,526 @@
+\input texinfo  @c -*-texinfo-*-
+@c %**start of header
+@setfilename dc.info
+@settitle dc, an arbitrary precision calculator
+@c %**end of header
+
+@c This file has the new style title page commands.
+@c Run `makeinfo' rather than `texinfo-format-buffer'.
+
+@c smallbook
+
+@c tex
+@c \overfullrule=0pt
+@c end tex
+
+@c Combine indices.
+@synindex cp fn
+@syncodeindex vr fn
+@syncodeindex ky fn
+@syncodeindex pg fn
+@syncodeindex tp fn
+
+@ifinfo
+@direntry
+* dc: (dc).                   Arbritrary precision RPN ``Desktop Calculator''.
+@end direntry
+This file documents @sc{dc}, an arbitrary precision calculator.
+
+Published by the Free Software Foundation, Inc.
+59 Temple Place, Suite 330
+Boston, MA 02111 USA
+
+Copyright (C) 1984, 1994, 1997, 1998, 2000 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage off
+
+@titlepage
+@title dc, an arbitrary precision calculator
+
+@author by Ken Pizzini
+@author original manual by Richard Stallman
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1994, 1997, 1998 Free Software Foundation, Inc.
+
+@sp 2
+Published by the Free Software Foundation, @*
+59 Temple Place, Suite 330 @*
+Boston, MA 02111 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@end titlepage
+@page
+
+@node Top, Introduction, (dir), (dir)
+
+@menu
+* Introduction::                Introduction
+* Invocation::                  Invocation
+* Printing Commands::           Printing Commands
+* Arithmetic::                  Arithmetic
+* Stack Control::               Stack Control
+* Registers::                   Registers
+* Parameters::                  Parameters
+* Strings::                     Strings
+* Status Inquiry::              Status Inquiry
+* Miscellaneous::               Other commands
+* Reporting bugs::              Reporting bugs
+@end menu
+
+@node Introduction, Invocation, Top, Top
+@comment  node-name,  next,  previous,  up
+@chapter Introduction
+
+@sc{dc} is a reverse-polish desk calculator
+which supports unlimited precision arithmetic.
+It also allows you to define and call macros.
+Normally @sc{dc} reads from the standard input;
+if any command arguments are given to it, they are filenames,
+and @sc{dc} reads and executes the contents of the files
+instead of reading from standard input.
+All normal output is to standard output;
+all error messages are written to standard error.
+
+To exit, use @samp{q}.
+@kbd{C-c} does not exit;
+it is used to abort macros that are looping, etc.
+(Currently this is not true; @kbd{C-c} does exit.)
+
+A reverse-polish calculator stores numbers on a stack.
+Entering a number pushes it on the stack.
+Arithmetic operations pop arguments off the stack and push the results.
+
+To enter a number in @sc{dc}, type the digits,
+with an optional decimal point.
+Exponential notation is not supported.
+To enter a negative number, begin the number with @samp{_}.
+@samp{-} cannot be used for this, as it is a binary operator
+for subtraction instead.
+To enter two numbers in succession,
+separate them with spaces or newlines.
+These have no meaning as commands.
+
+@node Invocation, Printing Commands, Introduction, Top
+@chapter Invocation
+
+@sc{dc} may be invoked with the following command-line options:
+@table @samp
+
+@item -e @var{expr}
+@item --expression=@var{expr}
+Evaluate @var{expr} as @sc{dc} commands.
+
+@item -f @var{file}
+@item --file=@var{file}
+Read and evaluate @sc{dc} commands from @var{file}.
+
+@item -h
+@item --help
+Print a usage message summarizing the command-line options, then exit.
+
+@item -V
+@item --version
+Print the version information for this program, then exit.
+@end table
+
+If any command-line parameters remain after processing the options,
+these parameters are interpreted as additional @var{file}s whose
+contents are read and evaluated.
+A file name of @code{-} refers to the standard input stream.
+If no @code{-e} option was specified, and no files were specified,
+then the standard input will be read for commands to evaluate.
+
+@node Printing Commands, Arithmetic, Invocation, Top
+@chapter Printing Commands
+
+@table @samp
+@item p
+Prints the value on the top of the stack,
+without altering the stack.
+A newline is printed after the value.
+
+@item n
+Prints the value on the top of the stack, popping it off,
+and does not print a newline after.
+(This command is a GNU extension.)
+
+@item P
+Pops off the value on top of the stack.
+If it it a string, it is simply printed without a trailing newline.
+Otherwise it is a number, and the integer portion of its absolute
+value is printed out as a "base (UCHAR_MAX+1)" byte stream.
+Assuming that (UCHAR_MAX+1) is 256
+(as it is on most machines with 8-bit bytes),
+the sequence
+@code{KSK 0k1/ [_1*]sx d0>x [256~aPd0<x]dsxx sxLKk}
+could also accomplish this function,
+except for the side-effect of clobbering the x register.
+(Details of the behavior with a number are a GNU extension.)
+
+@item f
+Prints the entire contents of the stack
+@c and the contents of all of the registers,
+without altering anything.
+This is a good command to use if you are lost or want
+to figure out what the effect of some command has been.
+@end table
+
+@node Arithmetic, Stack Control, Printing Commands, Top
+@chapter Arithmetic
+
+@table @samp
+@item +
+Pops two values off the stack, adds them, and pushes the result.
+The precision of the result is determined only
+by the values of the arguments, and is enough to be exact.
+
+@item -
+Pops two values, subtracts the first one popped
+from the second one popped, and pushes the result.
+
+@item *
+Pops two values, multiplies them, and pushes the result.
+The number of fraction digits in the result is the largest of
+the precision value,
+the number of fraction digits in the multiplier,
+or the number of fraction digits in the multiplicand;
+but in no event exceeding the number of digits required for
+an exact result.
+
+@item /
+Pops two values, divides the second one popped
+from the first one popped, and pushes the result.
+The number of fraction digits is specified by the precision value.
+
+@item %
+Pops two values,
+computes the remainder of the division that
+the @samp{/} command would do,
+and pushes that.
+The value computed is the same as that computed by
+the sequence @code{Sd dld/ Ld*-} .
+
+@item ~
+Pops two values,
+divides the second one popped from the first one popped.
+The quotient is pushed first, and the remainder is pushed next.
+The number of fraction digits used in the division
+is specified by the precision value.
+(The sequence @code{SdSn lnld/ LnLd%} could also accomplish
+this function, with slightly different error checking.)
+(This command is a GNU extension.)
+
+@item ^
+Pops two values and exponentiates,
+using the first value popped as the exponent
+and the second popped as the base.
+The fraction part of the exponent is ignored.
+The precision value specifies the number of fraction
+digits in the result.
+
+@item |
+Pops three values and computes a modular exponentiation.
+The first value popped is used as the reduction modulus;
+this value must be a non-zero number,
+and the result may not be accurate if the modulus
+is not an integer.
+The second popped is used as the exponent;
+this value must be a non-negative number,
+and any fractional part of this exponent will be ignored.
+The third value popped is the base which gets exponentiated,
+which should be an integer.
+For small integers this is like the sequence @code{Sm^Lm%},
+but, unlike @code{^}, this command will work with arbritrarily large exponents.
+(This command is a GNU extension.)
+
+@item v
+Pops one value, computes its square root, and pushes that.
+The precision value specifies the number of fraction digits
+in the result.
+@end table
+
+Most arithmetic operations are affected by the @emph{precision value},
+which you can set with the @samp{k} command.
+The default precision value is zero,
+which means that all arithmetic except for
+addition and subtraction produces integer results.
+
+@node Stack Control, Registers, Arithmetic, Top
+@chapter Stack Control
+
+@table @samp
+@item c
+Clears the stack, rendering it empty.
+
+@item d
+Duplicates the value on the top of the stack,
+pushing another copy of it.
+Thus, @samp{4d*p} computes 4 squared and prints it.
+
+@item r
+Reverses the order of (swaps) the top two values on the stack.
+(This command is a GNU extension.)
+@end table
+
+@node Registers, Parameters, Stack Control, Top
+@chapter Registers
+
+@sc{dc} provides at least 256 memory registers,
+each named by a single character.
+You can store a number in a register and retrieve it later.
+
+@table @samp
+@item s@var{r}
+Pop the value off the top of the stack and
+store it into register @var{r}.
+
+@item l@var{r}
+Copy the value in register @var{r},
+and push it onto the stack.
+This does not alter the contents of @var{r}.
+
+Each register also contains its own stack.
+The current register value is the top of the register's stack.
+
+@item S@var{r}
+Pop the value off the top of the (main) stack and
+push it onto the stack of register @var{r}.
+The previous value of the register becomes inaccessible.
+
+@item L@var{r}
+Pop the value off the top of register @var{r}'s stack
+and push it onto the main stack.
+The previous value in register @var{r}'s stack, if any,
+is now accessible via the @samp{l@var{r}} command.
+@end table
+@c 
+@c The @samp{f} command prints a list of all registers that have contents
+@c stored in them, together with their contents.
+@c Only the current contents of each register (the top of its stack)
+@c is printed.
+
+@node Parameters, Strings, Registers, Top
+@chapter Parameters
+
+@sc{dc} has three parameters that control its operation:
+the precision, the input radix, and the output radix.
+The precision specifies the number of fraction digits
+to keep in the result of most arithmetic operations.
+The input radix controls the interpretation of numbers typed in;
+@emph{all} numbers typed in use this radix.
+The output radix is used for printing numbers.
+
+The input and output radices are separate parameters;
+you can make them unequal, which can be useful or confusing.
+The input radix must be between 2 and 16 inclusive.
+The output radix must be at least 2.
+The precision must be zero or greater.
+The precision is always measured in decimal digits,
+regardless of the current input or output radix.
+
+@table @samp
+@item i
+Pops the value off the top of the stack
+and uses it to set the input radix.
+
+@item o
+Pops the value off the top of the stack
+and uses it to set the output radix.
+
+@item k
+Pops the value off the top of the stack
+and uses it to set the precision.
+
+@item I
+Pushes the current input radix on the stack.
+
+@item O
+Pushes the current output radix on the stack.
+
+@item K
+Pushes the current precision on the stack.
+
+@end table
+
+@node Strings, Status Inquiry, Parameters, Top
+@chapter Strings
+
+@sc{dc} can operate on strings as well as on numbers.
+The only things you can do with strings are print them
+and execute them as macros
+(which means that the contents of the string are processed as @sc{dc} commands).
+Both registers and the stack can hold strings,
+and @sc{dc} always knows whether any given object is a string or a number.
+Some commands such as arithmetic operations demand numbers
+as arguments and print errors if given strings.
+Other commands can accept either a number or a string;
+for example, the @samp{p} command can accept either and prints the object
+according to its type.
+
+@table @samp
+@item [@var{characters}]
+Makes a string containing @var{characters} and pushes it on the stack.
+For example, @samp{[foo]P} prints the characters @samp{foo}
+(with no newline).
+
+@item a
+The mnemonic for this is somewhat erroneous: asciify.
+The top-of-stack is popped.
+If it was a number, then the low-order byte of this number
+is converted into a string and pushed onto the stack.
+Otherwise the top-of-stack was a string,
+and the first character of that string is pushed back.
+(This command is a GNU extension.)
+
+@item x
+Pops a value off the stack and executes it as a macro.
+Normally it should be a string;
+if it is a number, it is simply pushed back onto the stack.
+For example, @samp{[1p]x} executes the macro @samp{1p},
+which pushes 1 on the stack and prints @samp{1} on a separate line.
+
+Macros are most often stored in registers;
+@samp{[1p]sa} stores a macro to print @samp{1} into register @samp{a},
+and @samp{lax} invokes the macro.
+
+@item >@var{r}
+Pops two values off the stack and compares them
+assuming they are numbers,
+executing the contents of register @var{r} as a macro
+if the original top-of-stack is greater.
+Thus, @samp{1 2>a} will invoke register @samp{a}'s contents
+and @samp{2 1>a} will not.
+
+@item !>@var{r}
+Similar but invokes the macro if the original top-of-stack is not greater
+(is less than or equal to) what was the second-to-top.
+
+@item <@var{r}
+Similar but invokes the macro if the original top-of-stack is less.
+
+@item !<@var{r}
+Similar but invokes the macro if the original top-of-stack is not less
+(is greater than or equal to) what was the second-to-top.
+
+@item =@var{r}
+Similar but invokes the macro if the two numbers popped are equal.
+@c This can also be validly used to compare two strings for equality.
+
+@item !=@var{r}
+Similar but invokes the macro if the two numbers popped are not equal.
+@c This can also be validly used to compare two strings for equality.
+
+@item ?
+Reads a line from the terminal and executes it.
+This command allows a macro to request input from the user.
+
+@item q
+During the execution of a macro,
+this command exits from the macro and also from the macro which invoked it.
+If called from the top level,
+or from a macro which was called directly from the top level,
+the @samp{q} command will cause @sc{dc} to exit.
+
+@item Q
+Pops a value off the stack and uses it as a count
+of levels of macro execution to be exited.
+Thus, @samp{3Q} exits three levels.
+@end table
+
+@node Status Inquiry, Miscellaneous, Strings, Top
+@chapter Status Inquiry
+
+@table @samp
+@item Z
+Pops a value off the stack,
+calculates the number of digits it has
+(or number of characters, if it is a string)
+and pushes that number.
+
+@item X
+Pops a value off the stack,
+calculates the number of fraction digits it has,
+and pushes that number.
+For a string, the value pushed is
+@c -1.
+0.
+
+@item z
+Pushes the current stack depth:
+the number of objects on the stack
+before the execution of the @samp{z} command.
+@end table
+
+@node Miscellaneous, Reporting bugs, Status Inquiry, Top
+@chapter Miscellaneous
+
+@table @samp
+@item !
+Will run the rest of the line as a system command.
+Note that parsing of the !<, !=, and !> commands take precidence,
+so if you want to run a command starting with <, =, or > you will
+need to add a space after the !.
+
+@item #
+Will interpret the rest of the line as a comment.
+(This command is a GNU extension.)
+
+@item :@var{r}
+Will pop the top two values off of the stack.
+The old second-to-top value will be stored in the array @var{r},
+indexed by the old top-of-stack value.
+
+@item ;@var{r}
+Pops the top-of-stack and uses it as an index into
+the array @var{r}.
+The selected value is then pushed onto the stack.
+@end table
+
+Note that each stacked instance of a register has its own
+array associated with it.
+Thus @samp{1 @var{0:a} 0S@var{a} 2 @var{0:a} L@var{a} @var{0;a}p}
+will print 1, because the 2 was stored in an instance of @var{0:a}
+that was later popped.
+
+@node Reporting bugs,  , Miscellaneous, Top
+@chapter Reporting bugs
+
+Email bug reports to @email{bug-dc@@gnu.org}.
+@contents
+@bye
diff --git a/doc/texinfo.tex b/doc/texinfo.tex
new file mode 100644 (file)
index 0000000..c49af9f
--- /dev/null
@@ -0,0 +1,5992 @@
+% 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{1999-09-25.10}
+%
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+% 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., 59 Temple Place - Suite 330,
+% Boston, MA 02111-1307, USA.
+%
+% In other words, you are welcome to use, share and improve this program.
+% You are forbidden to forbid anyone else to use, share and improve
+% what you give them.   Help stamp out software-hoarding!
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+%   ftp://ftp.gnu.org/gnu/texinfo.tex
+%   (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
+%   ftp://texinfo.org/tex/texinfo.tex
+%   ftp://us.ctan.org/macros/texinfo/texinfo.tex
+%   (and all CTAN mirrors, finger ctan@us.ctan.org for a list).
+%   /home/gd/gnu/doc/texinfo.tex on the GNU machines.
+% The texinfo.tex in any given Texinfo distribution could well be out
+% of date, so if that's what you're using, please check.
+% Texinfo has a small home page at http://texinfo.org/.
+%
+% 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, to process the dvi file; this makes foo.ps.
+% The extra runs of TeX 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.  You can get
+% the existing language-specific files from ftp://ftp.gnu.org/gnu/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}
+
+% Save some parts of plain tex 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\ptexi=\i
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexstar=\*
+\let\ptext=\t
+
+% We never want plain's outer \+ definition in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+\message{Basics,}
+\chardef\other=12
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% 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\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi
+\ifx\putwordDeffunc\undefined   \gdef\putwordDeffunc{Function}\fi
+\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+\hyphenation{ap-pen-dix}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{eshell}
+\hyphenation{white-space}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen \bindingoffset
+\newdimen \normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% 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.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\ifx\eTeXversion\undefined
+\def\loggingall{\tracingcommands2 \tracingstats2
+   \tracingpages1 \tracingoutput1 \tracinglostchars1
+   \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+   \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+\else
+\def\loggingall{\tracingcommands3 \tracingstats2
+   \tracingpages1 \tracingoutput1 \tracinglostchars1
+   \tracingmacros2 \tracingparagraphs1 \tracingrestores1
+   \tracingscantokens1 \tracingassigns1 \tracingifs1
+   \tracinggroups1 \tracingnesting2
+   \showboxbreadth\maxdimen\showboxdepth\maxdimen
+}%
+\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{%
+      \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
+      %
+      \ifpdfmakepagedest \pdfmkdest{\the\pageno} \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 \turnoffactive
+  \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#1{%
+  \let\next = #1%
+  \begingroup
+    \obeylines
+    \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse.  Otherwise, we're done.
+\def\parseargx{%
+  % \obeyedspace is defined far below, after the definition of \sepspaces.
+  \ifx\obeyedspace\temp
+    \expandafter\parseargdiscardspace
+  \else
+    \expandafter\parseargline
+  \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    %
+    % First remove any @c comment, then any @comment.
+    % Result of each macro is put in \toks0.
+    \argremovec #1\c\relax %
+    \expandafter\argremovecomment \the\toks0 \comment\relax %
+    %
+    % Call the caller's macro, saved as \next in \parsearg.
+    \expandafter\next\expandafter{\the\toks0}%
+  }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us.  The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+%    @end itemize  @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'.  Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands.  (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.)  But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+  \begingroup
+    \ignoreactivespaces
+    \edef\temp{#1}%
+    \global\toks0 = \expandafter{\temp}%
+  \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+  \obeyspaces
+  \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment; press RETURN to continue}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo  is the same as @foo, for now.
+\newhelp\EMsimple{Press RETURN to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+  \removeactivespaces{#1}%
+  \edef\endthing{\the\toks0}%
+  %
+  \expandafter\ifx\csname E\endthing\endcsname\relax
+    \expandafter\ifx\csname \endthing\endcsname\relax
+      % There's no \foo, i.e., no ``environment'' foo.
+      \errhelp = \EMsimple
+      \errmessage{Undefined command `@end \endthing'}%
+    \else
+      \unmatchedenderror\endthing
+    \fi
+  \else
+    % Everything's ok; the right environment has been started.
+    \csname E\endthing\endcsname
+  \fi
+}
+
+% There is an environment #1, but it hasn't been started.  Give an error.
+%
+\def\unmatchedenderror#1{%
+  \errhelp = \EMsimple
+  \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+  \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+% Single-spacing is done by various environments (specifically, in
+% \nonfillstart and \quotations).
+\newskip\singlespaceskip \singlespaceskip = 12.5pt
+\def\singlespace{%
+  % Why was this kern here?  It messes up equalizing space above and below
+  % environments.  --karl, 6may93
+  %{\advance \baselineskip by -\singlespaceskip
+  %\kern \baselineskip}%
+  \setleading \singlespaceskip
+}
+
+%% 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 actual \{ & \} command in an index.
+  \catcode`\{ = 12 \catcode`\} = 12
+  \catcode`\[ = 1 \catcode`\] = 2
+  \catcode`\@ = 0 \catcode`\\ = 12
+  @gdef@lbracecmd[\{]%
+  @gdef@rbracecmd[\}]%
+@endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @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
+% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% 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
+}
+
+% 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}
+
+% @. 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.
+%
+\def\group{\begingroup
+  \ifnum\catcode13=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  %
+  % The \vtop we start below 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.  (See p.82 of
+  % the TeXbook.)  Thus, space below is not quite equal to space
+  % above.  But it's pretty close.
+  \def\Egroup{%
+    \egroup           % End the \vtop.
+    \endgroup         % End the \group.
+  }%
+  %
+  \vtop\bgroup
+    % We have to put a strut on the last line in case the @group is in
+    % the midst of an example, rather than completely enclosing it.
+    % Otherwise, the interline space between the last line of the group
+    % and the first line afterwards is too small.  But we can't put the
+    % strut in \Egroup, since there it would be on a line by itself.
+    % Hence this just inserts a strut at the beginning of each line.
+    \everypar = {\strut}%
+    %
+    % Since we have a strut on every line, we don't need any of TeX's
+    % normal interline spacing.
+    \offinterlineskip
+    %
+    % OK, but now we have to do something about blank
+    % lines in the input in @example-like environments, which normally
+    % just turn into \lisppar, which will insert no space now that we've
+    % turned off the interline space.  Simplest is to make them be an
+    % empty paragraph.
+    \ifx\par\lisppar
+      \edef\par{\leavevmode \par}%
+      %
+      % Reset ^^M's definition to new definition of \par.
+      \obeylines
+    \fi
+    %
+    % 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
+}
+%
+% 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
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\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
+%}}
+
+\def\needx#1{%
+  % 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
+
+\let\br = \par
+
+% @dots{} output 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 minus 0.25fil
+    .\hss.\hss.%
+    \hskip 0pt plus 0.5fil minus 0.5fil
+  }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+  \leavevmode
+  \hbox to 2em{%
+    \hskip 0pt plus 0.25fil minus 0.25fil
+    .\hss.\hss.\hss.%
+    \hskip 0pt plus 0.5fil minus 0.5fil
+  }%
+  \spacefactor=3000
+}
+
+
+% @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.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+  \vtop to \strutdepth{\baselineskip\strutdepth\vss
+  \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
+%\hbox{{\rm#1}}\hfil\break}}
+
+% @include file    insert text of that file as input.
+% Allow normal characters that  we make active in the argument (a file name).
+\def\include{\begingroup
+  \catcode`\\=12
+  \catcode`~=12
+  \catcode`^=12
+  \catcode`_=12
+  \catcode`|=12
+  \catcode`<=12
+  \catcode`>=12
+  \catcode`+=12
+  \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+  % Read the included file in a group so nested @include's work.
+  \def\thisfile{#1}%
+  \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line   outputs that line, centered
+
+\def\center{\parsearg\centerzzz}
+\def\centerzzz #1{{\advance\hsize by -\leftskip
+\advance\hsize by -\rightskip
+\centerline{#1}}}
+
+% @sp n   outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\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.
+% We cannot implement @paragraphindent asis, though.
+% 
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\def\paragraphindent{\parsearg\doparagraphindent}
+\def\doparagraphindent#1{%
+  \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.
+\def\exampleindent{\parsearg\doexampleindent}
+\def\doexampleindent#1{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \lispnarrowing = 0pt
+    \else
+      \lispnarrowing = #1em
+    \fi
+  \fi
+}
+
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math means output in math mode.
+% We don't use $'s directly in the definition of \math because control
+% sequences like \math are expanded when the toc file is written.  Then,
+% we read the toc file back, the $'s will be normal characters (as they
+% should be, according to the definition of Texinfo).  So we must use a
+% control sequence to switch into and out of math mode.
+%
+% This isn't quite enough for @math to work properly in indices, but it
+% seems unlikely it will ever be needed there.
+%
+\let\implicitmath = $
+\def\math#1{\implicitmath #1\implicitmath}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+% @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{%
+   \iflinks
+     \readauxfile
+   \fi % \openindices needs to do some work in any case.
+   \openindices
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+   %
+   % If texinfo.cnf is present on the system, read it.
+   % Useful for site-wide @afourpaper, etc.
+   % Just to be on the safe side, close the input stream before the \input.
+   \openin 1 texinfo.cnf
+   \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
+   \closein1
+   \temp
+   %
+   \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
+
+\ifx\pdfoutput\undefined
+  \pdffalse
+  \let\pdfmkdest = \gobble
+  \let\pdfurl = \gobble
+  \let\endlink = \relax
+  \let\linkcolor = \relax
+  \let\pdfmakeoutlines = \relax
+\else
+  \pdftrue
+  \pdfoutput = 1
+  \input pdfcolor
+  \def\dopdfimage#1#2#3{%
+    \def\imagewidth{#2}%
+    \def\imageheight{#3}%
+    \ifnum\pdftexversion < 14
+      \pdfimage
+    \else
+      \pdfximage
+    \fi
+      \ifx\empty\imagewidth\else width \imagewidth \fi
+      \ifx\empty\imageheight\else height \imageheight \fi
+      {#1.pdf}%
+    \ifnum\pdftexversion < 14 \else
+      \pdfrefximage \pdflastximage
+    \fi}
+  \def\pdfmkdest#1{\pdfdest name{#1@} xyz}
+  \def\pdfmkpgn#1{#1@}
+  \let\linkcolor = \Cyan
+  \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 by1
+    \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+  \def\pdfmakeoutlines{{%
+    \openin 1 \jobname.toc
+    \ifeof 1\else\bgroup
+      \closein 1 
+      \indexnofonts
+      \def\tt{}
+      % thanh's hack / proper braces in bookmarks  
+      \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+      \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+      %
+      \def\chapentry ##1##2##3{}
+      \def\unnumbchapentry ##1##2{}
+      \def\secentry ##1##2##3##4{\advancenumber{chap##2}}
+      \def\unnumbsecentry ##1##2{}
+      \def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}}
+      \def\unnumbsubsecentry ##1##2{}
+      \def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}}
+      \def\unnumbsubsubsecentry ##1##2{}
+      \input \jobname.toc
+      \def\chapentry ##1##2##3{%
+        \pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}}
+      \def\unnumbchapentry ##1##2{%
+        \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+      \def\secentry ##1##2##3##4{%
+        \pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}}
+      \def\unnumbsecentry ##1##2{%
+        \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+      \def\subsecentry ##1##2##3##4##5{%
+        \pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}}
+      \def\unnumbsubsecentry ##1##2{%
+        \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+      \def\subsubsecentry ##1##2##3##4##5##6{%
+        \pdfoutline goto name{\pdfmkpgn{##6}}{##1}}
+      \def\unnumbsubsubsecentry ##1##2{%
+        \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+      \input \jobname.toc
+    \egroup\fi
+  }}
+  \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\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+  \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\@{@}%
+      \leavevmode\Red
+      \startlink attr{/Border [0 0 0]}%
+        user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+        % #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|
+    \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{\mkpgn{#1}}
+    \linkcolor #1\endlink}
+  \def\mkpgn#1{#1@} 
+  \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\fi % \ifx\pdfoutput
+
+
+\message{fonts,}
+% Font-change commands.
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+% Use Computer Modern fonts at \magstephalf (11pt).
+\newcount\mainmagstep
+\mainmagstep=\magstephalf
+
+% 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}
+
+\ifx\bigger\relax
+\let\mainmagstep=\magstep1
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
+\else
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+% Instead of cmb10, you many want to use cmbx10.
+% cmbx10 is a prettier font on its own, but cmb10
+% looks better when embedded in a line with cmr10.
+\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, etc.
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \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 title page:
+\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}
+
+% 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
+
+% \setfont\ssecrm\bxshape{10}{\magstep1}    % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1}    % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
+
+%\setfont\ssecrm\bfshape{10}{1315}      % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315}      % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315}      % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
+
+%\let\ssecbf=\ssecrm
+
+% 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}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% 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, 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 so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font.  Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example.  By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\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
+  \resetmathfonts}
+\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
+  \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
+  \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
+  \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
+  \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+\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
+  \resetmathfonts \setleading{11pt}}
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% 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\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{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\/\fi\fi\fi}
+\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+\let\cite=\smartslanted
+
+\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 = `- }
+
+\def\t#1{%
+  {\tt \rawbackslash \frenchspacing #1}%
+  \null
+}
+\let\ttfont=\t
+\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
+  }
+  %
+  % If we end up with any active - characters when handling the index,
+  % just treat them as a normal -.
+  \global\def\indexbreaks{\catcode`\-=\active \let-\realdash}
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}}
+\def\codex #1{\tclose{#1}\endgroup}
+
+%\let\exp=\tclose  %Was temporary
+
+% @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).
+\def\kbdinputstyle{\parsearg\kbdinputstylexxx}
+\def\kbdinputstylexxx#1{%
+  \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}%
+  \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is kbdinputdistinct.  (Too much of a hassle to call the macro,
+% the catcodes are wrong for parsearg to work.)
+\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}
+
+\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 @url, @env, @command quotes seem unnecessary, so use \code.
+\let\url=\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}
+
+% 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 downcases the argument and prints in smallcaps.
+\def\acronym#1{{\smallcaps \lowercase{#1}}}
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
+
+\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
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+        \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+   \let\subtitlerm=\tenrm
+   \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+   %
+   \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+   %
+   % Leave some space at the very top of the page.
+   \vglue\titlepagetopglue
+   %
+   % Now you can print the title using @title.
+   \def\title{\parsearg\titlezzz}%
+   \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
+                    % print a rule at the page bottom also.
+                    \finishedtitlepagefalse
+                    \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+   % No rule at page bottom unless we print one at the top with @title.
+   \finishedtitlepagetrue
+   %
+   % Now you can put text using @subtitle.
+   \def\subtitle{\parsearg\subtitlezzz}%
+   \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+   %
+   % @author should come last, but may come many times.
+   \def\author{\parsearg\authorzzz}%
+   \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+      {\authorfont \leftline{##1}}}%
+   %
+   % 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
+      \oldpage
+      \let\page = \oldpage
+      \hbox{}}%
+%   \def\page{\oldpage \hbox{}}
+}
+
+\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
+   %
+   % 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
+   %
+   \ifpdf \pdfmakepagedesttrue \fi
+   %
+   \HEADINGSon
+}
+
+\def\finishtitlepage{%
+   \vskip4pt \hrule height 2pt width \hsize
+   \vskip\titlepagebottomglue
+   \finishedtitlepagetrue
+}
+
+%%% 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\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\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
+}
+
+\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+%
+}% unbind the catcode of @.
+
+% @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
+% Produces Day Month Year style of output.
+\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}
+
+% @settitle line...  specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(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, @vtable, 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\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+                 \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+                 \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemfont{#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.  Unfortunately
+    % we can't prevent a possible page break at the following
+    % \baselineskip glue.
+    \nobreak
+    \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 table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+% Contains a kludge to get @end[description] to work.
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+% @table, @ftable, @vtable.
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1        \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1        \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1        \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+  \begingroup % ended by the @end itemize
+  \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey #1#2{%
+\aboveenvbreak %
+\itemmax=\itemindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \itemindent %
+\exdentamount=\itemindent
+\parindent = 0pt %
+\parskip = \smallskipamount %
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def#2{\endgraf\afterenvbreak\endgroup}%
+\def\itemcontents{#1}%
+\let\item=\itemizeitem}
+
+% Set sfcode to normal for the chars that usually have another value.
+% These are `.?!:;,'
+\def\frenchspacing{\sfcode46=1000 \sfcode63=1000 \sfcode33=1000
+  \sfcode58=1000 \sfcode59=1000 \sfcode44=1000 }
+
+% \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'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  \begingroup % ended by the @end enumerate
+  %
+  % 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 itemizey, 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
+  \itemizey{#1.}\Eenumerate\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}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{In hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @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.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+%     @multitable {Column 1 template} {Column 2 template} {Column 3
+%      template}
+% Not:
+%     @multitable {Column 1 template} {Column 2 template}
+%      {Column 3 template}
+
+% 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, @multitable or @end multitable 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 part of the @columnfraction before the decimal point, which
+% is presumably either 0 or the empty string (but we don't check, we
+% just throw it away).  #2 is the decimal part, which we use as the
+% percent of \hsize for this column.
+\def\pickupwholefraction#1.#2 {%
+  \global\advance\colcount by 1
+  \expandafter\xdef\csname col\the\colcount\endcsname{.#2\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 }% 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
+}
+
+% This used to have \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{&}
+
+% @multitable ... @end multitable definitions:
+%
+\def\multitable{\parsearg\dotable}
+\def\dotable#1{\bgroup
+  \vskip\parskip
+  \let\item\crcr
+  \tolerance=9500
+  \hbadness=9500
+  \setmultitablespacing
+  \parskip=\multitableparskip
+  \parindent=\multitableparindent
+  \overfullrule=0pt
+  \global\colcount=0
+  \def\Emultitable{\global\setpercentfalse\cr\egroup\egroup}%
+  %
+  % To parse everything between @multitable and @item:
+  \setuptable#1 \endsetuptable
+  %
+  % \everycr will reset column counter, \colcount, at the end of
+  % each line. Every column entry will cause \colcount to advance by one.
+  % The table preamble
+  % looks at the current \colcount to find the correct column width.
+  \everycr{\noalign{%
+  %
+  % \filbreak%% keeps underfull box messages off when table breaks over pages.
+  % 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.
+    \global\colcount=0\relax}}%
+  %
+  % 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\relax
+    \multistrut\vtop{\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\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,}
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+  \let\chapter=\relax
+  \let\unnumbered=\relax
+  \let\top=\relax
+  \let\unnumberedsec=\relax
+  \let\unnumberedsection=\relax
+  \let\unnumberedsubsec=\relax
+  \let\unnumberedsubsection=\relax
+  \let\unnumberedsubsubsec=\relax
+  \let\unnumberedsubsubsection=\relax
+  \let\section=\relax
+  \let\subsec=\relax
+  \let\subsubsec=\relax
+  \let\subsection=\relax
+  \let\subsubsection=\relax
+  \let\appendix=\relax
+  \let\appendixsec=\relax
+  \let\appendixsection=\relax
+  \let\appendixsubsec=\relax
+  \let\appendixsubsection=\relax
+  \let\appendixsubsubsec=\relax
+  \let\appendixsubsubsection=\relax
+  \let\contents=\relax
+  \let\smallbook=\relax
+  \let\titlepage=\relax
+}
+
+% Used in nested conditionals, where we have to parse the Texinfo source
+% and so want to turn off most commands, in case they are used
+% incorrectly.
+%
+\def\ignoremorecommands{%
+  \let\defcodeindex = \relax
+  \let\defcv = \relax
+  \let\deffn = \relax
+  \let\deffnx = \relax
+  \let\defindex = \relax
+  \let\defivar = \relax
+  \let\defmac = \relax
+  \let\defmethod = \relax
+  \let\defop = \relax
+  \let\defopt = \relax
+  \let\defspec = \relax
+  \let\deftp = \relax
+  \let\deftypefn = \relax
+  \let\deftypefun = \relax
+  \let\deftypeivar = \relax
+  \let\deftypeop = \relax
+  \let\deftypevar = \relax
+  \let\deftypevr = \relax
+  \let\defun = \relax
+  \let\defvar = \relax
+  \let\defvr = \relax
+  \let\ref = \relax
+  \let\xref = \relax
+  \let\printindex = \relax
+  \let\pxref = \relax
+  \let\settitle = \relax
+  \let\setchapternewpage = \relax
+  \let\setchapterstyle = \relax
+  \let\everyheading = \relax
+  \let\evenheading = \relax
+  \let\oddheading = \relax
+  \let\everyfooting = \relax
+  \let\evenfooting = \relax
+  \let\oddfooting = \relax
+  \let\headings = \relax
+  \let\include = \relax
+  \let\lowersections = \relax
+  \let\down = \relax
+  \let\raisesections = \relax
+  \let\up = \relax
+  \let\set = \relax
+  \let\clear = \relax
+  \let\item = \relax
+}
+
+% Ignore @ignore ... @end ignore.
+%
+\def\ignore{\doignore{ignore}}
+
+% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text.
+%
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\html{\doignore{html}}
+\def\menu{\doignore{menu}}
+\def\direntry{\doignore{direntry}}
+
+% @dircategory CATEGORY  -- specify a category of the dir file
+% which this file should belong to.  Ignore this in TeX.
+\let\dircategory = \comment
+
+% Ignore text until a line `@end #1'.
+%
+\def\doignore#1{\begingroup
+  % Don't complain about control sequences we have declared \outer.
+  \ignoresections
+  %
+  % Define a command to swallow text until we reach `@end #1'.
+  % This @ is a catcode 12 token (that is the normal catcode of @ in
+  % this texinfo.tex file).  We change the catcode of @ below to match.
+  \long\def\doignoretext##1@end #1{\enddoignore}%
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \catcode32 = 10
+  %
+  % Ignore braces, too, so mismatched braces don't cause trouble.
+  \catcode`\{ = 9
+  \catcode`\} = 9
+  %
+  % We must not have @c interpreted as a control sequence.
+  \catcode`\@ = 12
+  %
+  % Make the letter c a comment character so that the rest of the line
+  % will be ignored. This way, the document can have (for example)
+  %   @c @end ifinfo
+  % and the @end ifinfo will be properly ignored.
+  % (We've just changed @ to catcode 12.)
+  \catcode`\c = 14
+  %
+  % And now expand that command.
+  \doignoretext
+}
+
+% What we do to finish off ignored text.
+%
+\def\enddoignore{\endgroup\ignorespaces}%
+
+\newif\ifwarnedobs\warnedobsfalse
+\def\obstexwarn{%
+  \ifwarnedobs\relax\else
+  % We need to warn folks that they may have trouble with TeX 3.0.
+  % This uses \immediate\write16 rather than \message to get newlines.
+    \immediate\write16{}
+    \immediate\write16{WARNING: for users of Unix TeX 3.0!}
+    \immediate\write16{This manual trips a bug in TeX version 3.0 (tex hangs).}
+    \immediate\write16{If you are running another version of TeX, relax.}
+    \immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
+    \immediate\write16{  Then upgrade your TeX installation if you can.}
+    \immediate\write16{  (See ftp://ftp.gnu.org/pub/gnu/TeX.README.)}
+    \immediate\write16{If you are stuck with version 3.0, run the}
+    \immediate\write16{  script ``tex3patch'' from the Texinfo distribution}
+    \immediate\write16{  to use a workaround.}
+    \immediate\write16{}
+    \global\warnedobstrue
+    \fi
+}
+
+% **In TeX 3.0, setting text in \nullfont hangs tex.  For a
+% workaround (which requires the file ``dummy.tfm'' to be installed),
+% uncomment the following line:
+%%%%%\font\nullfont=dummy\let\obstexwarn=\relax
+
+% Ignore text, except that we keep track of conditional commands for
+% purposes of nesting, up to an `@end #1' command.
+%
+\def\nestedignore#1{%
+  \obstexwarn
+  % We must actually expand the ignored text to look for the @end
+  % command, so that nested ignore constructs work.  Thus, we put the
+  % text into a \vbox and then do nothing with the result.  To minimize
+  % the change of memory overflow, we follow the approach outlined on
+  % page 401 of the TeXbook: make the current font be a dummy font.
+  %
+  \setbox0 = \vbox\bgroup
+    % Don't complain about control sequences we have declared \outer.
+    \ignoresections
+    %
+    % Define `@end #1' to end the box, which will in turn undefine the
+    % @end command again.
+    \expandafter\def\csname E#1\endcsname{\egroup\ignorespaces}%
+    %
+    % We are going to be parsing Texinfo commands.  Most cause no
+    % trouble when they are used incorrectly, but some commands do
+    % complicated argument parsing or otherwise get confused, so we
+    % undefine them.
+    %
+    % We can't do anything about stray @-signs, unfortunately;
+    % they'll produce `undefined control sequence' errors.
+    \ignoremorecommands
+    %
+    % Set the current font to be \nullfont, a TeX primitive, and define
+    % all the font commands to also use \nullfont.  We don't use
+    % dummy.tfm, as suggested in the TeXbook, because not all sites
+    % might have that installed.  Therefore, math mode will still
+    % produce output, but that should be an extremely small amount of
+    % stuff compared to the main input.
+    %
+    \nullfont
+    \let\tenrm=\nullfont \let\tenit=\nullfont \let\tensl=\nullfont
+    \let\tenbf=\nullfont \let\tentt=\nullfont \let\smallcaps=\nullfont
+    \let\tensf=\nullfont
+    % Similarly for index fonts (mostly for their use in smallexample).
+    \let\smallrm=\nullfont \let\smallit=\nullfont \let\smallsl=\nullfont
+    \let\smallbf=\nullfont \let\smalltt=\nullfont \let\smallsc=\nullfont
+    \let\smallsf=\nullfont
+    %
+    % Don't complain when characters are missing from the fonts.
+    \tracinglostchars = 0
+    %
+    % Don't bother to do space factor calculations.
+    \frenchspacing
+    %
+    % Don't report underfull hboxes.
+    \hbadness = 10000
+    %
+    % Do minimal line-breaking.
+    \pretolerance = 10000
+    %
+    % Do not execute instructions in @tex
+    \def\tex{\doignore{tex}}%
+    % Do not execute macro definitions.
+    % `c' is a comment character, so the word `macro' will get cut off.
+    \def\macro{\doignore{ma}}%
+}
+
+% @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.  Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10
+  \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+  \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  \def\temp{#2}%
+  \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+  \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+  \fi
+  \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+{
+  \catcode`\_ = \active
+  %
+  % We might end up with active _ or - characters in the argument if
+  % we're called from @code, as @code{@value{foo-bar_}}.  So \let any
+  % such active characters to their normal equivalents.
+  \gdef\value{\begingroup
+    \catcode`\-=12 \catcode`\_=12
+    \indexbreaks \let_\normalunderscore
+    \valuexxx}
+}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we \let\value to this in \indexdummies).  Ones
+% whose names contain - or _ still won't work, but we can't do anything
+% about that.  The command has to be fully expandable, 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'']}%
+  \else
+    \csname SET#1\endcsname
+  \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\ifsetxxx}
+\def\ifsetxxx #1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \expandafter\ifsetfail
+  \else
+    \expandafter\ifsetsucceed
+  \fi
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\nestedignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\ifclearxxx}
+\def\ifclearxxx #1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \expandafter\ifclearsucceed
+  \else
+    \expandafter\ifclearfail
+  \fi
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\nestedignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text
+% following, through the first @end iftex (etc.).  Make `@end iftex'
+% (etc.) valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\def\ifnothtml{\conditionalsucceed{ifnothtml}}
+\def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
+\defineunmatchedend{iftex}
+\defineunmatchedend{ifnothtml}
+\defineunmatchedend{ifnotinfo}
+
+% We can't just want to start a group at @iftex (for example) and end it
+% at @end iftex, since then @set commands inside the conditional have no
+% effect (they'd get reverted at the end of the group).  So we must
+% define \Eiftex to redefine itself to be its previous value.  (We can't
+% just define it to fail again with an ``unmatched end'' error, since
+% the @ifset might be nested.)
+%
+\def\conditionalsucceed#1{%
+  \edef\temp{%
+    % Remember the current value of \E#1.
+    \let\nece{prevE#1} = \nece{E#1}%
+    %
+    % At the `@end #1', redefine \E#1 to be its previous value.
+    \def\nece{E#1}{\let\nece{E#1} = \nece{prevE#1}}%
+  }%
+  \temp
+}
+
+% We need to expand lots of \csname's, but we don't want to expand the
+% control sequences after we've constructed them.
+%
+\def\nece#1{\expandafter\noexpand\csname#1\endcsname}
+
+% @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\newcodeindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%
+    \noexpand\docodeindex{#1}}
+}
+
+\def\defcodeindex{\parsearg\newcodeindex}
+
+% @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.
+% The \closeout helps reduce unnecessary open files; the limit on the
+% Acorn RISC OS is a mere 16 files.
+\def\synindex#1 #2 {%
+  \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+  \expandafter\closeout\csname#1indfile\endcsname
+  \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+  \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+    \noexpand\doindex{#2}}%
+}
+
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+\def\syncodeindex#1 #2 {%
+  \expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
+  \expandafter\closeout\csname#1indfile\endcsname
+  \expandafter\let\csname#1indfile\endcsname=\synindexfoo
+  \expandafter\xdef\csname#1index\endcsname{% define \xxxindex
+    \noexpand\docodeindex{#2}}%
+}
+
+% 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}}}
+
+\def\indexdummies{%
+\def\ { }%
+% Take care of the plain tex accent commands.
+\def\"{\realbackslash "}%
+\def\`{\realbackslash `}%
+\def\'{\realbackslash '}%
+\def\^{\realbackslash ^}%
+\def\~{\realbackslash ~}%
+\def\={\realbackslash =}%
+\def\b{\realbackslash b}%
+\def\c{\realbackslash c}%
+\def\d{\realbackslash d}%
+\def\u{\realbackslash u}%
+\def\v{\realbackslash v}%
+\def\H{\realbackslash H}%
+% Take care of the plain tex special European modified letters.
+\def\oe{\realbackslash oe}%
+\def\ae{\realbackslash ae}%
+\def\aa{\realbackslash aa}%
+\def\OE{\realbackslash OE}%
+\def\AE{\realbackslash AE}%
+\def\AA{\realbackslash AA}%
+\def\o{\realbackslash o}%
+\def\O{\realbackslash O}%
+\def\l{\realbackslash l}%
+\def\L{\realbackslash L}%
+\def\ss{\realbackslash ss}%
+% Take care of texinfo commands likely to appear in an index entry.
+% (Must be a way to avoid doing expansion at all, and thus not have to
+% laboriously list every single command here.)
+\def\@{@}% will be @@ when we switch to @ as escape char.
+% 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
+\def\_{{\realbackslash _}}%
+\def\w{\realbackslash w }%
+\def\bf{\realbackslash bf }%
+%\def\rm{\realbackslash rm }%
+\def\sl{\realbackslash sl }%
+\def\sf{\realbackslash sf}%
+\def\tt{\realbackslash tt}%
+\def\gtr{\realbackslash gtr}%
+\def\less{\realbackslash less}%
+\def\hat{\realbackslash hat}%
+\def\TeX{\realbackslash TeX}%
+\def\dots{\realbackslash dots }%
+\def\result{\realbackslash result}%
+\def\equiv{\realbackslash equiv}%
+\def\expansion{\realbackslash expansion}%
+\def\print{\realbackslash print}%
+\def\error{\realbackslash error}%
+\def\point{\realbackslash point}%
+\def\copyright{\realbackslash copyright}%
+\def\tclose##1{\realbackslash tclose {##1}}%
+\def\code##1{\realbackslash code {##1}}%
+\def\uref##1{\realbackslash uref {##1}}%
+\def\url##1{\realbackslash url {##1}}%
+\def\env##1{\realbackslash env {##1}}%
+\def\command##1{\realbackslash command {##1}}%
+\def\option##1{\realbackslash option {##1}}%
+\def\dotless##1{\realbackslash dotless {##1}}%
+\def\samp##1{\realbackslash samp {##1}}%
+\def\,##1{\realbackslash ,{##1}}%
+\def\t##1{\realbackslash t {##1}}%
+\def\r##1{\realbackslash r {##1}}%
+\def\i##1{\realbackslash i {##1}}%
+\def\b##1{\realbackslash b {##1}}%
+\def\sc##1{\realbackslash sc {##1}}%
+\def\cite##1{\realbackslash cite {##1}}%
+\def\key##1{\realbackslash key {##1}}%
+\def\file##1{\realbackslash file {##1}}%
+\def\var##1{\realbackslash var {##1}}%
+\def\kbd##1{\realbackslash kbd {##1}}%
+\def\dfn##1{\realbackslash dfn {##1}}%
+\def\emph##1{\realbackslash emph {##1}}%
+\def\acronym##1{\realbackslash acronym {##1}}%
+%
+% Handle some cases of @value -- where the variable name does not
+% contain - or _, and the value does not contain any
+% (non-fully-expandable) commands.
+\let\value = \expandablevalue
+%
+\unsepspaces
+% Turn off macro expansion
+\turnoffmacros
+}
+
+% 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 \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+% \indexnofonts no-ops all font-change commands.
+% This is used when outputting the strings to sort the index by.
+\def\indexdummyfont#1{#1}
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+
+\def\indexnofonts{%
+% Just ignore accents.
+\let\,=\indexdummyfont
+\let\"=\indexdummyfont
+\let\`=\indexdummyfont
+\let\'=\indexdummyfont
+\let\^=\indexdummyfont
+\let\~=\indexdummyfont
+\let\==\indexdummyfont
+\let\b=\indexdummyfont
+\let\c=\indexdummyfont
+\let\d=\indexdummyfont
+\let\u=\indexdummyfont
+\let\v=\indexdummyfont
+\let\H=\indexdummyfont
+\let\dotless=\indexdummyfont
+% Take care of the plain tex special European modified letters.
+\def\oe{oe}%
+\def\ae{ae}%
+\def\aa{aa}%
+\def\OE{OE}%
+\def\AE{AE}%
+\def\AA{AA}%
+\def\o{o}%
+\def\O{O}%
+\def\l{l}%
+\def\L{L}%
+\def\ss{ss}%
+\let\w=\indexdummyfont
+\let\t=\indexdummyfont
+\let\r=\indexdummyfont
+\let\i=\indexdummyfont
+\let\b=\indexdummyfont
+\let\emph=\indexdummyfont
+\let\strong=\indexdummyfont
+\let\cite=\indexdummyfont
+\let\sc=\indexdummyfont
+%Don't no-op \tt, since it isn't a user-level command
+% and is used in the definitions of the active chars like <, >, |...
+%\let\tt=\indexdummyfont
+\let\tclose=\indexdummyfont
+\let\code=\indexdummyfont
+\let\url=\indexdummyfont
+\let\uref=\indexdummyfont
+\let\env=\indexdummyfont
+\let\acronym=\indexdummyfont
+\let\command=\indexdummyfont
+\let\option=\indexdummyfont
+\let\file=\indexdummyfont
+\let\samp=\indexdummyfont
+\let\kbd=\indexdummyfont
+\let\key=\indexdummyfont
+\let\var=\indexdummyfont
+\let\TeX=\indexdummytex
+\let\dots=\indexdummydots
+\def\@{@}%
+}
+
+% To define \realbackslash, we must make \ not be an escape.
+% We must first make another character (@) an escape
+% so we do not become unable to do a definition.
+
+{\catcode`\@=0 \catcode`\\=\other
+ @gdef@realbackslash{\}}
+
+\let\indexbackslash=0  %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% For \ifx comparisons.
+\def\emptymacro{\empty}
+
+% Most index entries go through here, but \dosubind is the general case.
+%
+\def\doind#1#2{\dosubind{#1}{#2}\empty}
+
+% 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 defuns, which call us directly.
+%
+\def\dosubind#1#2#3{%
+  % Put the index entry in the margin if desired.
+  \ifx\SETmarginindex\relax\else
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+  \fi
+  {%
+    \count255=\lastpenalty
+    {%
+      \indexdummies % Must do this here, since \bf, etc expand at this stage
+      \escapechar=`\\
+      {%
+        \let\folio = 0% We will expand all macros now EXCEPT \folio.
+        \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+        % so it will be output as is; and it will print as backslash.
+        %
+        \def\thirdarg{#3}%
+        %
+        % If third arg is present, precede it with space in sort key.
+        \ifx\thirdarg\emptymacro
+          \let\subentry = \empty
+        \else
+          \def\subentry{ #3}%
+        \fi
+        %
+        % First process the index entry with all font commands turned
+        % off to get the string to sort by.
+        {\indexnofonts \xdef\indexsorttmp{#2\subentry}}%
+        %
+        % Now the real index entry with the fonts.
+        \toks0 = {#2}%
+        %
+        % If third (subentry) arg is present, add it to the index
+        % string.  And include a space.
+        \ifx\thirdarg\emptymacro \else
+          \toks0 = \expandafter{\the\toks0 \space #3}%
+        \fi
+        %
+        % 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, texindex reduces to
+        % two when writing the .??s sorted result.
+        \edef\temp{%
+          \write\csname#1indfile\endcsname{%
+            \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+        }%
+        %
+        % 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.
+        %
+        \iflinks
+          \ifvmode
+            \skip0 = \lastskip
+            \ifdim\lastskip = 0pt \else \nobreak\vskip-\lastskip \fi
+          \fi
+          %
+          \temp % do the write
+          %
+          %
+          \ifvmode \ifdim\skip0 = 0pt \else \nobreak\vskip\skip0 \fi \fi
+        \fi
+      }%
+    }%
+    \penalty\count255
+  }%
+}
+
+% 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).
+%
+\def\printindex{\parsearg\doprintindex}
+\def\doprintindex#1{\begingroup
+  \dobreak \chapheadingskip{10000}%
+  %
+  \smallfonts \rm
+  \tolerance = 9500
+  \indexbreaks
+  %
+  % 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{\rawbackslashxx}%
+      \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
+}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin.  It is used for index and table of contents
+% entries.  The paragraph is indented by \leftskip.
+%
+\def\entry#1#2{\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
+  %
+  % Start a ``paragraph'' for the index entry so the line breaking
+  % parameters we've set above will have an effect.
+  \noindent
+  %
+  % Insert the text of the index entry.  TeX will do line-breaking on it.
+  #1%
+  % 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{#2}%
+  \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#2.\ \the\toksA % The page number ends the paragraph.
+    \else
+      \ #2% The page number ends the paragraph.
+    \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 #2\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.)
+  \advance\vsize by -\ht\partialpage
+  \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
+  %
+  % box0 will be the left-hand column, box2 the right.
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar
+  \unvbox255
+  \penalty\outputpenalty
+}
+\def\pagesofar{%
+  % Re-output the contents of the output page -- any previous material,
+  % followed by the two boxes we just split, in box0 and box2.
+  \unvbox\partialpage
+  %
+  \hsize = \doublecolumnhsize
+  \wd0=\hsize \wd2=\hsize
+  \hbox to\pagewidth{\box0\hfil\box2}%
+}
+\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
+}
+\def\balancecolumns{%
+  % Called at the end of the double column material.
+  \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.
+
+\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 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.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raise/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
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \chapterzzz{#2}
+\or
+  \seczzz{#2}
+\or
+  \numberedsubseczzz{#2}
+\or
+  \numberedsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \chapterzzz{#2}
+  \else
+    \numberedsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \appendixzzz{#2}
+\or
+  \appendixsectionzzz{#2}
+\or
+  \appendixsubseczzz{#2}
+\or
+  \appendixsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \appendixzzz{#2}
+  \else
+    \appendixsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+  \unnumberedzzz{#2}
+\or
+  \unnumberedseczzz{#2}
+\or
+  \unnumberedsubseczzz{#2}
+\or
+  \unnumberedsubsubseczzz{#2}
+\else
+  \ifnum \absseclevel<0
+    \unnumberedzzz{#2}
+  \else
+    \unnumberedsubsubseczzz{#2}
+  \fi
+\fi
+}
+
+% @chapter, @appendix, @unnumbered.
+\def\thischaptername{No Chapter Title}
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy #1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \chapno by 1 \message{\putwordChapter\space \the\chapno}%
+\chapmacro {#1}{\the\chapno}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+% We don't substitute the actual chapter name into \thischapter
+% because we don't want its macros evaluated now.
+\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+                                  {\the\chapno}}}%
+\temp
+\donoderef
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+\global\advance \appendixno by 1
+\message{\putwordAppendix\space \appendixletter}%
+\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\gdef\thissection{#1}%
+\gdef\thischaptername{#1}%
+\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash chapentry{\the\toks0}%
+                       {\putwordAppendix{} \appendixletter}}}%
+\temp
+\appendixnoderef
+\global\let\section = \appendixsec
+\global\let\subsection = \appendixsubsec
+\global\let\subsubsection = \appendixsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
+% @top is like @unnumbered.
+\outer\def\top{\parsearg\unnumberedyyy}
+
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz #1{%
+\secno=0 \subsecno=0 \subsubsecno=0
+%
+% 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)}%
+%
+\unnumbchapmacro {#1}%
+\gdef\thischapter{#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}%
+\temp
+\unnumbnoderef
+\global\let\section = \unnumberedsec
+\global\let\subsection = \unnumberedsubsec
+\global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% Sections.
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy #1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz #1{%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+                                  {\the\chapno}{\the\secno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy #1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz #1{%
+\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
+\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash secentry{\the\toks0}%
+                                  {\appendixletter}{\the\secno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy #1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz #1{%
+\plainsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% Subsections.
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy #1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz #1{%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+                                    {\the\chapno}{\the\secno}{\the\subsecno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy #1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz #1{%
+\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
+\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsecentry{\the\toks0}%
+                                {\appendixletter}{\the\secno}{\the\subsecno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz #1{%
+\plainsubsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry%
+                                    {\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% Subsubsections.
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy #1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz #1{%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+  {\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+\temp
+\donoderef
+\nobreak
+}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy #1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz #1{%
+\gdef\thissection{#1}\global\advance \subsubsecno by 1 %
+\subsubsecheading {#1}
+  {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash subsubsecentry{\the\toks0}%
+  {\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
+\temp
+\appendixnoderef
+\nobreak
+}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz #1{%
+\plainsubsubsecheading {#1}\gdef\thissection{#1}%
+\toks0 = {#1}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry%
+                                    {\the\toks0}}}%
+\temp
+\unnumbnoderef
+\nobreak
+}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they should now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% 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.
+\global\let\section = \numberedsec
+\global\let\subsection = \numberedsubsec
+\global\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{\parsearg\majorheadingzzz}
+\def\majorheadingzzz #1{%
+{\advance\chapheadingskip by 10pt \chapbreak }%
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 200}
+
+\def\chapheading{\parsearg\chapheadingzzz}
+\def\chapheadingzzz #1{\chapbreak %
+{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                  \parindent=0pt\raggedright
+                  \rm #1\hfill}}\bigskip \par\penalty 200}
+
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\plainsecheading}
+\def\subheading{\parsearg\plainsubsecheading}
+\def\subsubheading{\parsearg\plainsubsubsecheading}
+
+% 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}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% 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
+
+\def\CHAPFplain{
+\global\let\chapmacro=\chfplain
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+% Plain chapter opening.
+% #1 is the text, #2 the chapter number or empty if unnumbered.
+\def\chfplain#1#2{%
+  \pchapsepmacro
+  {%
+    \chapfonts \rm
+    \def\chapnum{#2}%
+    \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent = \wd0 \centerparametersmaybe
+          \unhbox0 #1\par}%
+  }%
+  \nobreak\bigskip % no page break after a chapter title
+  \nobreak
+}
+
+% Plain opening for unnumbered.
+\def\unnchfplain#1{\chfplain{#1}{}}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+  \def\centerparametersmaybe{%
+    \advance\rightskip by 3\rightskip
+    \leftskip = \rightskip
+    \parfillskip = 0pt
+  }%
+  \chfplain{#1}{}%
+}}
+
+\CHAPFplain % The default
+
+\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\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
+
+% Subsection titles.
+\newskip \subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
+
+% Subsubsection titles.
+\let\subsubsecheadingskip = \subsecheadingskip
+\let\subsubsecheadingbreak = \subsecheadingbreak
+\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
+
+
+% Print any size section title.
+%
+% #1 is the section type (sec/subsec/subsubsec), #2 is the section
+% number (maybe empty), #3 the text.
+\def\sectionheading#1#2#3{%
+  {%
+    \expandafter\advance\csname #1headingskip\endcsname by \parskip
+    \csname #1headingbreak\endcsname
+  }%
+  {%
+    % Switch to the right set of fonts.
+    \csname #1fonts\endcsname \rm
+    %
+    % Only insert the separating space if we have a section number.
+    \def\secnum{#2}%
+    \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+    %
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent = \wd0 % zero if no section number
+          \unhbox0 #3}%
+  }%
+  \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc.  We supply {\folio} at the end of the
+% argument, which will end up as the last argument to the \...entry macro.
+%
+% We open the .toc file here instead of at @setfilename or any other
+% given time so that @contents can be put in the document anywhere.
+%
+\newif\iftocfileopened
+\def\writetocentry#1{%
+  \iftocfileopened\else
+    \immediate\openout\tocfile = \jobname.toc
+    \global\tocfileopenedtrue
+  \fi
+  \iflinks \write\tocfile{#1{\folio}}\fi
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Finish up the main text and 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.
+   \unnumbchapmacro{#1}\def\thischapter{}%
+   \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 \pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+   \startcontents{\putwordTOC}%
+     \openin 1 \jobname.toc
+     \ifeof 1 \else
+       \closein 1
+       \input \jobname.toc
+     \fi
+     \vfill \eject
+     \contentsalignmacro % in case @setchapternewpage odd is in effect
+     \pdfmakeoutlines
+   \endgroup
+   \lastnegativepageno = \pageno
+   \pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+   \startcontents{\putwordShortTOC}%
+      %
+      \let\chapentry = \shortchapentry
+      \let\unnumbchapentry = \shortunnumberedentry
+      % We want a true roman here for the page numbers.
+      \secfonts
+      \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+      \rm
+      \hyphenpenalty = 10000
+      \advance\baselineskip by 1pt % Open it up a little.
+      \def\secentry ##1##2##3##4{}
+      \def\unnumbsecentry ##1##2{}
+      \def\subsecentry ##1##2##3##4##5{}
+      \def\unnumbsubsecentry ##1##2{}
+      \def\subsubsecentry ##1##2##3##4##5##6{}
+      \def\unnumbsubsubsecentry ##1##2{}
+      \openin 1 \jobname.toc
+      \ifeof 1 \else
+        \closein 1
+        \input \jobname.toc
+      \fi
+     \vfill \eject
+     \contentsalignmacro % in case @setchapternewpage odd is in effect
+   \endgroup
+   \lastnegativepageno = \pageno
+   \pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+\ifpdf
+  \pdfcatalog{/PageMode /UseOutlines}%
+\fi
+
+% 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, ...
+
+% Chapter-level things, for both the long and short contents.
+\def\chapentry#1#2#3{\dochapentry{#2\labelspace#1}{#3}}
+
+% See comments in \dochapentry re vbox and related settings
+\def\shortchapentry#1#2#3{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#3\egroup}%
+}
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g. `Appendix A' for an appendix, or `3' for a chapter.
+% We could simplify the code here by writing out an \appendixentry
+% command in the toc file for appendices, instead of using \chapentry
+% for both, but it doesn't seem worth it.
+%
+\newdimen\shortappendixwidth
+%
+\def\shortchaplabel#1{%
+  % Compute width of word "Appendix", may change with language.
+  \setbox0 = \hbox{\shortcontrm \putwordAppendix}%
+  \shortappendixwidth = \wd0
+  %
+  % We typeset #1 in a box of constant width, regardless of the text of
+  % #1, so the chapter titles will come out aligned.
+  \setbox0 = \hbox{#1}%
+  \dimen0 = \ifdim\wd0 > \shortappendixwidth \shortappendixwidth \else 0pt \fi
+  %
+  % This space should be plenty, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in by \shortchapentry above.)
+  \advance\dimen0 by 1.1em
+  \hbox to \dimen0{#1\hfil}%
+}
+
+\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
+\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno\bgroup#2\egroup}}
+
+% Sections.
+\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
+\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+
+% Subsections.
+\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
+\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+
+% And subsubsections.
+\def\subsubsecentry#1#2#3#4#5#6{%
+  \dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
+\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 3pc
+
+% 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}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here.  (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+\def\tocentry#1#2{\begingroup
+  \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+  % Do not use \turnoffactive in these arguments.  Since the toc is
+  % typeset in cmr, so characters such as _ would come out wrong; we
+  % have to do the usual translation tricks.
+  \entry{#1}{#2}%
+\endgroup}
+
+% 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}
+\let\subsecentryfonts = \textfonts
+\let\subsubsecentryfonts = \textfonts
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% 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.
+% Furthermore, these definitions must come after we define our fonts.
+\newbox\dblarrowbox    \newbox\longdblarrowbox
+\newbox\pushcharbox    \newbox\bullbox
+\newbox\equivbox       \newbox\errorbox
+
+%{\tentt
+%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
+%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
+%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
+%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
+% Adapted from the manmac format (p.420 of TeXbook)
+%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
+%                                      depth .1ex\hfil}
+%}
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+\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}}
+
+% Adapted from the TeXbook's \boxit.
+{\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}
+
+\global\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}
+
+% The @error{} command.
+\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.
+
+\def\tex{\begingroup
+  \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+  \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+  \catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
+  \catcode `\%=14
+  \catcode 43=12 % plus
+  \catcode`\"=12
+  \catcode`\==12
+  \catcode`\|=12
+  \catcode`\<=12
+  \catcode`\>=12
+  \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\{=\ptexlbrace
+  \let\+=\tabalign
+  \let\}=\ptexrbrace
+  \let\*=\ptexstar
+  \let\t=\ptext
+  %
+  \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+  \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+  \def\@{@}%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @endlisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @endlisp (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}
+
+% 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.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is.  This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% 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{{\advance\envskipamount by \parskip
+\endgraf \ifdim\lastskip<\envskipamount
+\removelastskip \penalty-50 \vskip\envskipamount \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
+
+\long\def\cartouche{%
+\begingroup
+        \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
+                                \hsize=\cartinner
+                                \kern3pt
+                                \begingroup
+                                        \baselineskip=\normbskip
+                                        \lineskip=\normlskip
+                                        \parskip=\normpskip
+                                        \vskip -\parskip
+\def\Ecartouche{%
+                                \endgroup
+                                \kern3pt
+                        \egroup
+                        \kern3pt\vrule
+                        \hskip\rskip
+                \egroup
+                \cartbot
+        \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \inENV % This group ends at the end of the body
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \singlespace
+  \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
+    \let\exdent=\nofillexdent
+    \let\nonarrowing=\relax
+  \fi
+}
+
+% Define the \E... control sequence only if we are inside the particular
+% environment, so the error checking in \end will work.
+%
+% To end an @example-like environment, we first end the paragraph (via
+% \afterenvbreak's vertical glue), and then the group.  That way we keep
+% the zero \parskip that the environments set -- \parskip glue will be
+% inserted at the beginning of the next paragraph in the document, after
+% the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}
+
+% @lisp: indented, narrowed, typewriter font.
+\def\lisp{\begingroup
+  \nonfillstart
+  \let\Elisp = \nonfillfinish
+  \tt
+  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+  \gobble       % eat return
+}
+
+% @example: Same as @lisp.
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+
+% @small... is usually equivalent to the non-small (@smallbook
+% redefines).  We must call \example (or whatever) last in the
+% definition, since it reads the return following the @example (or
+% whatever) command.
+%
+% This actually allows (for example) @end display inside an
+% @smalldisplay.  Too bad, but makeinfo will catch the error anyway.
+%
+\def\smalldisplay{\begingroup\def\Esmalldisplay{\nonfillfinish\endgroup}\display}
+\def\smallexample{\begingroup\def\Esmallexample{\nonfillfinish\endgroup}\lisp}
+\def\smallformat{\begingroup\def\Esmallformat{\nonfillfinish\endgroup}\format}
+\def\smalllisp{\begingroup\def\Esmalllisp{\nonfillfinish\endgroup}\lisp}
+
+% Real @smallexample and @smalllisp (when @smallbook): use smaller fonts.
+% Originally contributed by Pavel@xerox.
+\def\smalllispx{\begingroup
+  \def\Esmalllisp{\nonfillfinish\endgroup}%
+  \def\Esmallexample{\nonfillfinish\endgroup}%
+  \smallfonts
+  \lisp
+}
+
+% @display: same as @lisp except keep current font.
+%
+\def\display{\begingroup
+  \nonfillstart
+  \let\Edisplay = \nonfillfinish
+  \gobble
+}
+
+% @smalldisplay (when @smallbook): @display plus smaller fonts.
+%
+\def\smalldisplayx{\begingroup
+  \def\Esmalldisplay{\nonfillfinish\endgroup}%
+  \smallfonts \rm
+  \display
+}
+
+% @format: same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eformat = \nonfillfinish
+  \gobble
+}
+
+% @smallformat (when @smallbook): @format plus smaller fonts.
+%
+\def\smallformatx{\begingroup
+  \def\Esmallformat{\nonfillfinish\endgroup}%
+  \smallfonts \rm
+  \format
+}
+
+% @flushleft (same as @format).
+%
+\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format}
+
+% @flushright.
+%
+\def\flushright{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eflushright = \nonfillfinish
+  \advance\leftskip by 0pt plus 1fill
+  \gobble
+}
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+  \begingroup\inENV %This group ends at the end of the @quotation body
+  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+  \singlespace
+  \parindent=0pt
+  % We have retained a nonzero parskip for the environment, since we're
+  % doing normal filling. So to avoid extra space below the environment...
+  \def\Equotation{\parskip = 0pt \nonfillfinish}%
+  %
+  % @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
+}
+
+
+\message{defuns,}
+% @defun etc.
+
+% Allow user to change definition object font (\df) internally
+\def\setdeffont #1 {\csname DEF#1\endcsname}
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deftypemargin \deftypemargin=12pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+% define \functionparens, which makes ( and ) and & do special things.
+% \functionparens affects the group it is contained in.
+\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 = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% 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.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
+  \global\advance\parencount by 1
+}
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+  % also in that case restore the outer-level definition of (.
+  \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+  \global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text.  This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
+\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
+\let\ampnr = \&
+\def\lbrb{{\bf\char`\[}}
+\def\rbrb{{\bf\char`\]}}
+
+% Active &'s sneak into the index arguments, so make sure it's defined.
+{
+  \catcode`& = 13
+  \global\let& = \ampnr
+}
+
+% First, defname, which formats the header line itself.
+% #1 should be the function name.
+% #2 should be the type of definition, such as "Function".
+
+\def\defname #1#2{%
+% Get the values of \leftskip and \rightskip as they were
+% outside the @def...
+\dimen2=\leftskip
+\advance\dimen2 by -\defbodyindent
+\noindent
+\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
+\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
+\parshape 2 0in \dimen0 \defargsindent \dimen1
+% Now output arg 2 ("Function" or some such)
+% ending at \deftypemargin from the right margin,
+% but stuck inside a box of width 0 so it does not interfere with linebreaking
+{% Adjust \hsize to exclude the ambient margins,
+% so that \rightline will obey them.
+\advance \hsize by -\dimen2
+\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}%
+% Make all lines underfull and no complaints:
+\tolerance=10000 \hbadness=10000
+\advance\leftskip by -\defbodyindent
+\exdentamount=\defbodyindent
+{\df #1}\enskip        % Generate function name
+}
+
+% Actually process the body of a definition
+% #1 should be the terminating control sequence, such as \Edefun.
+% #2 should be the "another name" control sequence, such as \defunx.
+% #3 should be the control sequence that actually processes the header,
+%    such as \defunheader.
+
+\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active % 61 is `='
+\obeylines\activeparens\spacesplit#3}
+
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence for consecutive fns (which we define).
+% #3 is the control sequence to call to resume processing.
+% #4, delimited by the space, is the class name.
+%
+\def\defmethparsebody#1#2#3#4 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+
+% Used for @deftypemethod and @deftypeivar.
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence for consecutive fns (which we define).
+% #3 is the control sequence to call to resume processing.
+% #4, delimited by a space, is the class name.
+% #5 is the method's return type.
+%
+\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV
+  \medbreak
+  \def#1{\endgraf\endgroup\medbreak}%
+  \def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}%
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+  \begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}}
+
+% Used for @deftypeop.  The change from \deftypemethparsebody is an
+% extra argument at the beginning which is the `category', instead of it
+% being the hardwired string `Method' or `Instance Variable'.  We have
+% to account for this both in the \...x definition and in parsing the
+% input at hand.  Thus also need a control sequence (passed as #5) for
+% the \E... definition to assign the category name to.
+% 
+\def\deftypeopparsebody#1#2#3#4#5 #6 {\begingroup\inENV
+  \medbreak
+  \def#1{\endgraf\endgroup\medbreak}%
+  \def#2##1 ##2 ##3 {%
+    \def#4{##1}%
+    \begingroup\obeylines\activeparens\spacesplit{#3{##2}{##3}}}%
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+  \begingroup\obeylines\activeparens\spacesplit{#3{#5}{#6}}}
+
+\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+
+\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2{\begingroup\obeylines\spacesplit#3}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup %
+\catcode 61=\active %
+\obeylines\spacesplit#3}
+
+% This is used for \def{tp,vr}parsebody.  It could probably be used for
+% some of the others, too, with some judicious conditionals.
+%
+\def\parsebodycommon#1#2#3{%
+  \begingroup\inENV %
+  \medbreak %
+  % Define the end token that this defining construct specifies
+  % so that it will exit this group.
+  \def#1{\endgraf\endgroup\medbreak}%
+  \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+  \begingroup\obeylines
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument.  Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name.  That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any).  That's what this does.
+%
+\def\removeemptybraces\empty#1\relax{#1}
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+  #1{\removeemptybraces#2\relax}{#3}%
+}%
+
+\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
+\medbreak %
+% Define the end token that this defining construct specifies
+% so that it will exit this group.
+\def#1{\endgraf\endgroup\medbreak}%
+\def#2##1 ##2 {\def#4{##1}%
+\begingroup\obeylines\spacesplit{#3{##2}}}%
+\parindent=0in
+\advance\leftskip by \defbodyindent
+\exdentamount=\defbodyindent
+\begingroup\obeylines\spacesplit{#3{#5}}}
+
+% Split up #2 at the first space token.
+% call #1 with two arguments:
+%  the first is all of #2 before the space token,
+%  the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+
+{\obeylines
+\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
+\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
+\ifx\relax #3%
+#1{#2}{}\else #1{#2}{#3#4}\fi}}
+
+% So much for the things common to all kinds of definitions.
+
+% Define @defun.
+
+% First, define the processing that is wanted for arguments of \defun
+% Use this to expand the args and terminate the paragraph they make up
+
+\def\defunargs#1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Set the font temporarily and use \font in case \setfont made \tensl a macro.
+{\tensl\hyphenchar\font=0}%
+#1%
+{\tensl\hyphenchar\font=45}%
+\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\nobreak\vskip -\parskip\nobreak
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+\interlinepenalty=10000
+\advance\rightskip by 0pt plus 1fil
+\endgraf\nobreak\vskip -\parskip\nobreak
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDeffunc}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type.  #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypefun}%
+\deftypefunargs {#3}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$$$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$$${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification.  #2 is the data type.  #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+%               at least some C++ text from working
+\defname {\defheaderxcond#2\relax$$$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefmac}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefspec}%
+\defunargs {#2}\endgroup %
+\catcode 61=\other % Turn off change made in \defparsebody
+}
+
+% @defop CATEGORY CLASS OPERATION ARG...
+%
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+%
+\def\defopheader#1#2#3{%
+\dosubind {fn}{\code{#2}}{\putwordon\ #1}% Make entry in function index
+\begingroup\defname {#2}{\defoptype\ \putwordon\ #1}%
+\defunargs {#3}\endgroup %
+}
+
+% @deftypeop CATEGORY CLASS TYPE OPERATION ARG...
+%
+\def\deftypeop #1 {\def\deftypeopcategory{#1}%
+  \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader
+                       \deftypeopcategory}
+%
+% #1 is the class name, #2 the data type, #3 the operation name, #4 the args.
+\def\deftypeopheader#1#2#3#4{%
+  \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+  \begingroup
+    \defname{\defheaderxcond#2\relax$$$#3}
+            {\deftypeopcategory\ \putwordon\ \code{#1}}%
+    \deftypefunargs{#4}%
+  \endgroup
+}
+
+% @deftypemethod CLASS TYPE METHOD ARG...
+%
+\def\deftypemethod{%
+  \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+%
+% #1 is the class name, #2 the data type, #3 the method name, #4 the args.
+\def\deftypemethodheader#1#2#3#4{%
+  \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+  \begingroup
+    \defname{\defheaderxcond#2\relax$$$#3}{\putwordMethodon\ \code{#1}}%
+    \deftypefunargs{#4}%
+  \endgroup
+}
+
+% @deftypeivar CLASS TYPE VARNAME
+%
+\def\deftypeivar{%
+  \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader}
+%
+% #1 is the class name, #2 the data type, #3 the variable name.
+\def\deftypeivarheader#1#2#3{%
+  \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index
+  \begingroup
+    \defname{#3}{\putwordInstanceVariableof\ \code{#1}}%
+    \defvarargs{#3}%
+  \endgroup
+}
+
+% @defmethod == @defop Method
+%
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+%
+% #1 is the class name, #2 the method name, #3 the args.
+\def\defmethodheader#1#2#3{%
+  \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index
+  \begingroup
+    \defname{#2}{\putwordMethodon\ \code{#1}}%
+    \defunargs{#3}%
+  \endgroup
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+\dosubind {vr}{\code{#2}}{\putwordof\ #1}% Make entry in var index
+\begingroup\defname {#2}{\defcvtype\ \putwordof\ #1}%
+\defvarargs {#3}\endgroup %
+}
+
+% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME
+%
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+%
+\def\defivarheader#1#2#3{%
+  \dosubind {vr}{\code{#2}}{\putwordof\ #1}% entry in var index
+  \begingroup
+    \defname{#2}{\putwordInstanceVariableof\ #1}%
+    \defvarargs{#3}%
+  \endgroup
+}
+
+% @defvar
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefvar}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefopt}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type.  #2 is the name, perhaps followed by text that
+% is actually part of the data type, which should not be put into the index.
+\def\deftypevarheader #1#2{%
+\dovarind#2 \relax% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$$$#2}{\putwordDeftypevar}%
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak
+\endgroup}
+\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\dovarind#3 \relax%
+\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
+\interlinepenalty=10000
+\endgraf\nobreak\vskip -\parskip\nobreak
+\endgroup}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% These definitions are used if you use @defunx (etc.)
+% anywhere other than immediately after a @defun or @defunx.
+% 
+\def\defcvx#1 {\errmessage{@defcvx in invalid context}}
+\def\deffnx#1 {\errmessage{@deffnx in invalid context}}
+\def\defivarx#1 {\errmessage{@defivarx in invalid context}}
+\def\defmacx#1 {\errmessage{@defmacx in invalid context}}
+\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\defopx#1 {\errmessage{@defopx in invalid context}}
+\def\defspecx#1 {\errmessage{@defspecx in invalid context}}
+\def\deftpx#1 {\errmessage{@deftpx in invalid context}}
+\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}}
+\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}}
+\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}}
+\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}}
+\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}}
+\def\defunx#1 {\errmessage{@defunx in invalid context}}
+\def\defvarx#1 {\errmessage{@defvarx in invalid context}}
+\def\defvrx#1 {\errmessage{@defvrx in invalid context}}
+
+
+\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\scanmacro#1{%
+   \begingroup \newlinechar`\^^M
+   % Undo catcode changes of \startcontents and \doprintindex
+   \catcode`\@=0 \catcode`\\=12 \escapechar=`\@
+   % Append \endinput to make sure that TeX does not see the ending newline.
+   \toks0={#1\endinput}%
+   \immediate\openout\macscribble=\jobname.tmp
+   \immediate\write\macscribble{\the\toks0}%
+   \immediate\closeout\macscribble
+   \let\xeatspaces\eatspaces
+   \input \jobname.tmp
+   \endgroup
+}
+\else
+\def\scanmacro#1{%
+\begingroup \newlinechar`\^^M
+% Undo catcode changes of \startcontents and \doprintindex
+\catcode`\@=0 \catcode`\\=12 \escapechar=`\@
+\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup}
+\fi
+
+\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.
+% Thisdoes \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=12\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\macrobodyctxt{%
+  \catcode`\~=12
+  \catcode`\^=12
+  \catcode`\_=12
+  \catcode`\|=12
+  \catcode`\<=12
+  \catcode`\>=12
+  \catcode`\+=12
+  \catcode`\{=12
+  \catcode`\}=12
+  \catcode`\@=12
+  \catcode`\^^M=12
+  \usembodybackslash}
+
+\def\macroargctxt{%
+  \catcode`\~=12
+  \catcode`\^=12
+  \catcode`\_=12
+  \catcode`\|=12
+  \catcode`\<=12
+  \catcode`\>=12
+  \catcode`\+=12
+  \catcode`\@=12
+  \catcode`\\=12}
+
+% \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{The name \the\macname\space is reserved}\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}
+
+\def\unmacro{\parsearg\unmacroxxx}
+\def\unmacroxxx#1{%
+  \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
+      \edef\tempa{\expandafter\noexpand\csname#1\endcsname}%
+      \def\do##1{%
+        \def\tempb{##1}%
+        \ifx\tempa\tempb
+          % remove this
+        \else
+          \toks0 = \expandafter{\newmacrolist\do}%
+          \edef\newmacrolist{\the\toks0\expandafter\noexpand\tempa}%
+        \fi}%
+      \def\newmacrolist{}%
+      % Execute macro list to define \newmacrolist
+      \macrolist
+      \global\let\macrolist\newmacrolist
+    \endgroup
+  \else
+    \errmessage{Macro #1 not defined}%
+  \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 mant 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}
+
+
+% @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{\begingroup\obeyspaces\parsearg\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{\ignoreactivespaces
+\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=%
+           \expandafter\noexpand\csname#2\endcsname}%
+\expandafter\endgroup\next}
+
+
+\message{cross references,}
+% @xref etc.
+
+\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 job is to define \lastnode.
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx [#1,]}
+\def\nodexxx[#1,#2]{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\relax
+
+% The sectioning commands (@chapter, etc.) call these.
+\def\donoderef{%
+  \ifx\lastnode\relax\else
+    \expandafter\expandafter\expandafter\setref{\lastnode}%
+      {Ysectionnumberandtype}%
+    \global\let\lastnode=\relax
+  \fi
+}
+\def\unnumbnoderef{%
+  \ifx\lastnode\relax\else
+    \expandafter\expandafter\expandafter\setref{\lastnode}{Ynothing}%
+    \global\let\lastnode=\relax
+  \fi
+}
+\def\appendixnoderef{%
+  \ifx\lastnode\relax\else
+    \expandafter\expandafter\expandafter\setref{\lastnode}%
+      {Yappendixletterandtype}%
+    \global\let\lastnode=\relax
+  \fi
+}
+
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME, namely
+% NAME-title, NAME-pg, and NAME-SNT.  Called from \foonoderef.  We have
+% to set \indexdummies so commands such as @code in a section title
+% aren't expanded.  It would be nicer not to expand the titles in the
+% first place, but there's so many layers that that is hard to do.
+%
+\def\setref#1#2{{%
+  \indexdummies
+  \pdfmkdest{#1}%
+  \dosetq{#1-title}{Ytitle}%
+  \dosetq{#1-pg}{Ypagenumber}%
+  \dosetq{#1-snt}{#2}%
+}}
+
+% @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\printednodename{\ignorespaces #3}%
+  \setbox1=\hbox{\printedmanual}%
+  \setbox0=\hbox{\printednodename}%
+  \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\printednodename{\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\printednodename{\ignorespaces #1}%
+      \else
+        \ifhavexrefs
+          % We know the real title if we have the xref values.
+          \def\printednodename{\refx{#1-title}{}}%
+        \else
+          % Otherwise just copy the Info node name.
+          \def\printednodename{\ignorespaces #1}%
+        \fi%
+      \fi
+    \fi
+  \fi
+  %
+  % 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.
+  \ifpdf
+    \leavevmode
+    \getfilename{#4}%
+    \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{#1@}%
+    \fi
+    \linkcolor
+  \fi
+  %
+  \ifdim \wd1 > 0pt
+    \putwordsection{} ``\printednodename'' \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.
+    {\normalturnoffactive
+     % 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
+    }%
+    % [mynode],
+    [\printednodename],\space
+    % page 3
+    \turnoffactive \putwordpage\tie\refx{#1-pg}{}%
+  \fi
+  \endlink
+\endgroup}
+
+% \dosetq is the interface for calls from other macros
+
+% Use \normalturnoffactive so that punctuation chars such as underscore
+% and backslash work in node names.  (\turnoffactive doesn't do \.)
+\def\dosetq#1#2{%
+  {\let\folio=0%
+   \normalturnoffactive
+   \edef\next{\write\auxfile{\internalsetq{#1}{#2}}}%
+   \iflinks
+     \next
+   \fi
+  }%
+}
+
+% \internalsetq {foo}{page} expands into
+% CHARACTERS 'xrdef {foo}{...expansion of \Ypage...}
+% When the aux file is read, ' is the escape character
+
+\def\internalsetq #1#2{'xrdef {#1}{\csname #2\endcsname}}
+
+% Things to be expanded by \internalsetq
+
+\def\Ypagenumber{\folio}
+
+\def\Ytitle{\thissection}
+
+\def\Ynothing{}
+
+\def\Ysectionnumberandtype{%
+\ifnum\secno=0 \putwordChapter\xreftie\the\chapno %
+\else \ifnum \subsecno=0 \putwordSection\xreftie\the\chapno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\def\Yappendixletterandtype{%
+\ifnum\secno=0 \putwordAppendix\xreftie'char\the\appendixno{}%
+\else \ifnum \subsecno=0 \putwordSection\xreftie'char\the\appendixno.\the\secno %
+\else \ifnum \subsubsecno=0 %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno %
+\else %
+\putwordSection\xreftie'char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno %
+\fi \fi \fi }
+
+\gdef\xreftie{'tie}
+
+% 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 % Non-3.0.
+\else
+  \def\linenumber{\the\inputlineno:\space}
+\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{%
+  \expandafter\ifx\csname X#1\endcsname\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.
+    \csname X#1\endcsname
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.
+%
+\def\xrdef#1{\begingroup
+  % Reenable \ as an escape while reading the second argument.
+  \catcode`\\ = 0
+  \afterassignment\endgroup
+  \expandafter\gdef\csname X#1\endcsname
+}
+
+% Read the last existing aux file, if any.  No error if none exists.
+\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
+  \catcode`\@=\other
+  \catcode`\^=\other
+  % It was suggested to define this as 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
+  \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
+  % 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
+    }%
+  }%
+  % The aux file uses ' as the escape (for now).
+  % Turn off \ as an escape so we do not lose on
+  % entries which were dumped with control sequences in their names.
+  % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+  % Reference to such entries still does not work the way one would wish,
+  % but at least they do not bomb out when the aux file is read in.
+  \catcode`\{=1
+  \catcode`\}=2
+  \catcode`\%=\other
+  \catcode`\'=0
+  \catcode`\\=\other
+  %
+  \openin 1 \jobname.aux
+  \ifeof 1 \else
+    \closein 1
+    \input \jobname.aux
+    \global\havexrefstrue
+    \global\warnedobstrue
+  \fi
+  % Open the new aux file.  TeX will close it automatically at exit.
+  \openout\auxfile=\jobname.aux
+\endgroup}
+
+
+% 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
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \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}\/\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \footnotezzz
+}%
+
+% 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 fail inside footnotes because the tokens are fixed when
+% the footnote is read.  --karl, 16nov96.
+%
+\long\gdef\footnotezzz{\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.
+  \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
+  %
+  % Hang the footnote text off the number.
+  \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
+}
+\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+  \else\let\next\f@t\fi \next}
+\def\f@@t{\bgroup\aftergroup\@foot\let\next}
+\def\f@t#1{#1\@foot}
+\def\@foot{\strut\par\egroup}
+
+}%end \catcode `\@=11
+
+% 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
+  }%
+}
+
+% @| 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
+    }%
+  }%
+}
+
+% 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}
+
+% @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
+  \closein 1
+  % Do not bother showing banner with post-v2.7 epsf.tex (available in
+  % doc/epsf.tex until it shows up on ctan).
+  \def\epsfannounce{\toks0 = }%
+  \input epsf.tex
+\fi
+%
+% 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 just the usual extra ignored arg for parsing this stuff.
+\def\imagexxx#1,#2,#3,#4\finish{%
+  \ifpdf
+    \centerline{\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
+    \begingroup
+      \catcode`\^^M = 5 % in case we're inside an example
+      % If the image is by itself, center it.
+      \ifvmode
+        \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
+        \centerline{\epsfbox{#1.eps}}%
+        \bigbreak
+      \else
+        % In the middle of a paragraph, no extra space.
+        \epsfbox{#1.eps}%
+      \fi
+    \endgroup
+  \fi
+}
+
+
+\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.
+%
+\def\documentlanguage{\parsearg\dodocumentlanguage}
+\def\dodocumentlanguage#1{%
+  \tex % read txi-??.tex file in plain TeX.
+  % Read the file if it exists.
+  \openin 1 txi-#1.tex
+  \ifeof1
+    \errhelp = \nolanghelp
+    \errmessage{Cannot read language file txi-#1.tex}%
+    \let\temp = \relax
+  \else
+    \def\temp{\input txi-#1.tex }%
+  \fi
+  \temp
+  \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.  Then whoever calls us can
+% set \parskip and call \setleading for \baselineskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6{%
+  \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
+  %
+  \parindent = \defaultparindent
+  \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \setleading{13.2pt}%
+  %
+  % If page is nothing but text, make it come out even.
+  \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+\def\smallbook{{\globaldefs = 1
+  \parskip = 2pt plus 1pt
+  \setleading{12pt}%
+  %
+  \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}%
+  %
+  \lispnarrowing = 0.3in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \deftypemargin = 0pt
+  \defbodyindent = .5cm
+  %
+  \let\smalldisplay = \smalldisplayx
+  \let\smallexample = \smalllispx
+  \let\smallformat = \smallformatx
+  \let\smalllisp = \smalllispx
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+  \setleading{12pt}%
+  \parskip = 3pt plus 2pt minus 1pt
+  %
+  \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}%
+  %
+  \tolerance = 700
+  \hfuzz = 1pt
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper.  Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex{{\globaldefs = 1
+  \setleading{13.6pt}%
+  %
+  \afourpaper
+  \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}%
+  %
+  \globaldefs = 0
+}}
+
+% Use @afourwide to print on European A4 paper in wide format.
+\def\afourwide{%
+  \afourpaper
+  \internalpagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}%
+  %
+  \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.
+%
+\def\pagesizes{\parsearg\pagesizesxxx}
+\def\pagesizesxxx#1{\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{13.2pt}%
+  %
+  \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}%
+}}
+
+% 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{$}
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, 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.06em \vbox{\hrule width.3em height.1ex}}
+
+\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}
+%\catcode 27=\active
+%\def^^[{$\diamondsuit$}
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% 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
+
+% \rawbackslashxx output one backslash character in current font
+\global\chardef\rawbackslashxx=`\\
+%{\catcode`\\=\other
+%@gdef@rawbackslashxx{\}}
+
+% \rawbackslash redefines \ as input to do \rawbackslashxx.
+{\catcode`\\=\active
+@gdef@rawbackslash{@let\=@rawbackslashxx }}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+% \catcode 17=0   % Define control-q
+\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}
+
+@def@normalturnoffactive{@let"=@normaldoublequote
+@let\=@normalbackslash
+@let~=@normaltilde
+@let^=@normalcaret
+@let_=@normalunderscore
+@let|=@normalverticalbar
+@let<=@normalless
+@let>=@normalgreater
+@let+=@normalplus
+@let$=@normaldollar}
+
+% 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 Set initial fonts.
+@textfonts
+@rm
+
+
+@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:
diff --git a/h/getopt.h b/h/getopt.h
new file mode 100644 (file)
index 0000000..f3696d9
--- /dev/null
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+   Copyright (C) 1989, 90, 91, 92, 93, 94 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., 675 Mass Ave,
+Cambridge, MA 02139, 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 EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+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 */
diff --git a/h/number.h b/h/number.h
new file mode 100644 (file)
index 0000000..8d78120
--- /dev/null
@@ -0,0 +1,153 @@
+/* number.h: Arbitrary precision numbers header file. */
+/*
+    Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 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 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; see the file COPYING.  If not, write to:
+
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111-1307 USA.
+
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#ifndef _NUMBER_H_
+#define _NUMBER_H_
+
+typedef enum {PLUS, MINUS} sign;
+
+typedef struct bc_struct *bc_num;
+
+typedef struct bc_struct
+    {
+      sign  n_sign;
+      int   n_len;     /* The number of digits before the decimal point. */
+      int   n_scale;   /* The number of digits after the decimal point. */
+      int   n_refs;     /* The number of pointers to this number. */
+      bc_num n_next;   /* Linked list for available list. */
+      char *n_ptr;     /* The pointer to the actual storage.
+                          If NULL, n_value points to the inside of
+                          another number (bc_multiply...) and should
+                          not be "freed." */
+      char *n_value;   /* The number. Not zero char terminated.
+                          May not point to the same place as n_ptr as
+                          in the case of leading zeros generated. */
+    } bc_struct;
+
+
+/* The base used in storing the numbers in n_value above.
+   Currently this MUST be 10. */
+
+#define BASE 10
+
+/*  Some useful macros and constants. */
+
+#define CH_VAL(c)     (c - '0')
+#define BCD_CHAR(d)   (d + '0')
+
+#ifdef MIN
+#undef MIN
+#undef MAX
+#endif
+#define MAX(a,b)      ((a)>(b)?(a):(b))
+#define MIN(a,b)      ((a)>(b)?(b):(a))
+#define ODD(a)        ((a)&1)
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 0x7ffffff
+#endif
+
+
+/* Global numbers. */
+extern bc_num _zero_;
+extern bc_num _one_;
+extern bc_num _two_;
+
+
+/* Function Prototypes */
+
+/* Define the _PROTOTYPE macro if it is needed. */
+
+#ifndef _PROTOTYPE
+#ifdef __STDC__
+#define _PROTOTYPE(func, args) func args
+#else
+#define _PROTOTYPE(func, args) func()
+#endif
+#endif
+
+_PROTOTYPE(void bc_init_numbers, (void));
+
+_PROTOTYPE(bc_num bc_new_num, (int length, int scale));
+
+_PROTOTYPE(void bc_free_num, (bc_num *num));
+
+_PROTOTYPE(bc_num bc_copy_num, (bc_num num));
+
+_PROTOTYPE(void bc_init_num, (bc_num *num));
+
+_PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale));
+
+_PROTOTYPE(char *bc_num2str, (bc_num num));
+
+_PROTOTYPE(void bc_int2num, (bc_num *num, int val));
+
+_PROTOTYPE(long bc_num2long, (bc_num num));
+
+_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2));
+
+_PROTOTYPE(char bc_is_zero, (bc_num num));
+
+_PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale));
+
+_PROTOTYPE(char bc_is_neg, (bc_num num));
+
+_PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
+
+_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
+
+_PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale));
+
+_PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale));
+
+_PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result,
+                          int scale));
+
+_PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot,
+                          bc_num *rem, int scale));
+
+_PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod,
+                            bc_num *result, int scale));
+
+_PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result,
+                          int scale));
+
+_PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
+
+_PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
+                            int leading_zero));
+
+#endif
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..ab74c88
--- /dev/null
@@ -0,0 +1,238 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# 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.
+#
+
+
+# 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}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644 (file)
index 0000000..6f74b4d
--- /dev/null
@@ -0,0 +1,26 @@
+## Process this file with automake to produce Makefile.in
+noinst_LIBRARIES = libbc.a
+
+INCLUDES = -I. -I.. -I$(srcdir)/../h
+
+libbc_a_SOURCES = getopt.c getopt1.c vfprintf.c number.c
+
+DEFS = @DEFS@ $(DEFSADD)
+
+CFLAGS = @CFLAGS@ -Wall -funsigned-char
+
+MAINTAINERCLEANFILES = Makefile.in number.c
+
+newnumber.o: number.c muldigits.h
+       $(CC) $(CFLAGS) $(INCLUDES) -c -DMULDIGITS -o newnumber.o $(srcdir)/number.c
+
+muldigits.h: testmul
+       @echo "The following may take up to 10 minutes."
+       testmul > muldigits.h
+
+testmul: testmul.o number.o
+       $(CC) $(CFLAGS) -o testmul testmul.o number.o
+
+specialnumber: newnumber.o
+       cp newnumber.o number.o
+
diff --git a/lib/Makefile.in b/lib/Makefile.in
new file mode 100644 (file)
index 0000000..5ffa593
--- /dev/null
@@ -0,0 +1,283 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 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.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+LEX = @LEX@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+READLINELIB = @READLINELIB@
+VERSION = @VERSION@
+YACC = @YACC@
+
+noinst_LIBRARIES = libbc.a
+
+INCLUDES = -I. -I.. -I$(srcdir)/../h
+
+libbc_a_SOURCES = getopt.c getopt1.c vfprintf.c number.c
+
+DEFS = @DEFS@ $(DEFSADD)
+
+CFLAGS = @CFLAGS@ -Wall -funsigned-char
+
+MAINTAINERCLEANFILES = Makefile.in number.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libbc_a_LIBADD = 
+libbc_a_OBJECTS =  getopt.o getopt1.o vfprintf.o number.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(libbc_a_SOURCES)
+OBJECTS = $(libbc_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps lib/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+       -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+       $(COMPILE) -c $<
+
+.s.o:
+       $(COMPILE) -c $<
+
+.S.o:
+       $(COMPILE) -c $<
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libbc.a: $(libbc_a_OBJECTS) $(libbc_a_DEPENDENCIES)
+       -rm -f libbc.a
+       $(AR) cru libbc.a $(libbc_a_OBJECTS) $(libbc_a_LIBADD)
+       $(RANLIB) libbc.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       here=`pwd` && cd $(srcdir) \
+         && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)'; \
+       unique=`for i in $$list; do echo $$i; done | \
+         awk '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = lib
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pr $$/$$file $(distdir)/$$file; \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+getopt.o: getopt.c ../config.h ../h/getopt.h
+getopt1.o: getopt1.c ../config.h ../h/getopt.h
+number.o: number.c ../config.h ../h/number.h
+vfprintf.o: vfprintf.c ../config.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+               mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+               mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+               distclean-tags distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+               maintainer-clean-compile maintainer-clean-tags \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+newnumber.o: number.c muldigits.h
+       $(CC) $(CFLAGS) $(INCLUDES) -c -DMULDIGITS -o newnumber.o $(srcdir)/number.c
+
+muldigits.h: testmul
+       @echo "The following may take up to 10 minutes."
+       testmul > muldigits.h
+
+testmul: testmul.o number.o
+       $(CC) $(CFLAGS) -o testmul testmul.o number.o
+
+specialnumber: newnumber.o
+       cp newnumber.o number.o
+
+# 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:
diff --git a/lib/getopt.c b/lib/getopt.c
new file mode 100644 (file)
index 0000000..23ce064
--- /dev/null
@@ -0,0 +1,752 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+   before changing it!
+
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+       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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+\f
+/* 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.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* 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>
+#endif /* GNU C library.  */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+   but it behaves differently for the user, since it allows the user
+   to intersperse the options with the other arguments.
+
+   As `getopt' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Setting the environment variable POSIXLY_CORRECT disables permutation.
+   Then the behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns EOF, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* XXX 1003.2 says this must be 1 before any call.  */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+   in which the last option character we returned was found.
+   This allows us to pick up the scan where we left off.
+
+   If this is zero, or a null string, it means resume the scan
+   by advancing to the next ARGV-element.  */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   If the caller did not specify anything,
+   the default is REQUIRE_ORDER if the environment variable
+   POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+   REQUIRE_ORDER means don't recognize them as options;
+   stop option processing when the first non-option is seen.
+   This is what Unix does.
+   This mode of operation is selected by either setting the environment
+   variable POSIXLY_CORRECT, or using `+' as the first character
+   of the list of option characters.
+
+   PERMUTE is the default.  We permute the contents of ARGV as we scan,
+   so that eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written to
+   expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were written
+   to expect options and other ARGV-elements in any order and that care about
+   the ordering of the two.  We describe each non-option ARGV-element
+   as if it were the argument of an option with character code 1.
+   Using `-' as the first character of the list of option characters
+   selects this mode of operation.
+
+   The special argument `--' forces an end of option-scanning regardless
+   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+
+static enum
+{
+  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable.  */
+static char *posixly_correct;
+\f
+#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
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+     const char *str;
+     int chr;
+{
+  while (*str)
+    {
+      if (*str == chr)
+       return (char *) str;
+      str++;
+    }
+  return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+   If not using GCC, it is ok not to declare it.  */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+   That was relevant to code that was here before.  */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+   and has done so at least since version 2.4.5. -- rms.  */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+\f
+/* Handle permutation of arguments.  */
+
+/* Describe the part of ARGV that contains non-options that have
+   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
+   `last_nonopt' is the index after the last of them.  */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (argv)
+     char **argv;
+{
+  int bottom = first_nonopt;
+  int middle = last_nonopt;
+  int top = optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+       {
+         /* Bottom segment is the short one.  */
+         int len = middle - bottom;
+         register int i;
+
+         /* Swap it with the top part of the top segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[top - (middle - bottom) + i];
+             argv[top - (middle - bottom) + i] = tem;
+           }
+         /* Exclude the moved bottom segment from further swapping.  */
+         top -= len;
+       }
+      else
+       {
+         /* Top segment is the short one.  */
+         int len = top - middle;
+         register int i;
+
+         /* Swap it with the bottom part of the bottom segment.  */
+         for (i = 0; i < len; i++)
+           {
+             tem = argv[bottom + i];
+             argv[bottom + i] = argv[middle + i];
+             argv[middle + i] = tem;
+           }
+         /* Exclude the moved top segment from further swapping.  */
+         bottom += len;
+       }
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  first_nonopt += (optind - last_nonopt);
+  last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (optstring)
+     const char *optstring;
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  first_nonopt = last_nonopt = optind = 1;
+
+  nextchar = NULL;
+
+  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;
+
+  return optstring;
+}
+\f
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns `EOF'.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   The elements of ARGV aren't really const, because we permute them.
+   But we pretend they're const in the prototype to be compatible
+   with other systems.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.  */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+     const struct option *longopts;
+     int *longind;
+     int long_only;
+{
+  optarg = NULL;
+
+  if (optind == 0)
+    optstring = _getopt_initialize (optstring);
+
+  if (nextchar == NULL || *nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      if (ordering == PERMUTE)
+       {
+         /* If we have just processed some options following some non-options,
+            exchange them so that the options come first.  */
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (last_nonopt != optind)
+           first_nonopt = optind;
+
+         /* Skip any additional non-options
+            and extend the range of non-options previously skipped.  */
+
+         while (optind < argc
+                && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+           optind++;
+         last_nonopt = optind;
+       }
+
+      /* The special ARGV-element `--' means premature end of options.
+        Skip it like a null option,
+        then exchange with previous non-options as if it were an option,
+        then skip everything else like a non-option.  */
+
+      if (optind != argc && !strcmp (argv[optind], "--"))
+       {
+         optind++;
+
+         if (first_nonopt != last_nonopt && last_nonopt != optind)
+           exchange ((char **) argv);
+         else if (first_nonopt == last_nonopt)
+           first_nonopt = optind;
+         last_nonopt = argc;
+
+         optind = argc;
+       }
+
+      /* If we have done all the ARGV-elements, stop the scan
+        and back over any non-options that we skipped and permuted.  */
+
+      if (optind == argc)
+       {
+         /* Set the next-arg-index to point at the non-options
+            that we previously skipped, so the caller will digest them.  */
+         if (first_nonopt != last_nonopt)
+           optind = first_nonopt;
+         return EOF;
+       }
+
+      /* If we have come to a non-option and did not permute it,
+        either stop the scan or describe it to the caller and pass it by.  */
+
+      if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+       {
+         if (ordering == REQUIRE_ORDER)
+           return EOF;
+         optarg = argv[optind++];
+         return 1;
+       }
+
+      /* We have found another option-ARGV-element.
+        Skip the initial punctuation.  */
+
+      nextchar = (argv[optind] + 1
+                 + (longopts != NULL && argv[optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[optind][1] == '-'
+         || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound;
+      int option_index;
+
+      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+       /* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+        or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+       if (!strncmp (p->name, nextchar, nameend - nextchar))
+         {
+           if (nameend - nextchar == strlen (p->name))
+             {
+               /* Exact match found.  */
+               pfound = p;
+               indfound = option_index;
+               exact = 1;
+               break;
+             }
+           else if (pfound == NULL)
+             {
+               /* First nonexact match found.  */
+               pfound = p;
+               indfound = option_index;
+             }
+           else
+             /* Second or later nonexact match found.  */
+             ambig = 1;
+         }
+
+      if (ambig && !exact)
+       {
+         if (opterr)
+           fprintf (stderr, "%s: option `%s' is ambiguous\n",
+                    argv[0], argv[optind]);
+         nextchar += strlen (nextchar);
+         optind++;
+         return '?';
+       }
+
+      if (pfound != NULL)
+       {
+         option_index = indfound;
+         optind++;
+         if (*nameend)
+           {
+             /* Don't test has_arg with >, because some C compilers don't
+                allow it to be used on enums.  */
+             if (pfound->has_arg)
+               optarg = nameend + 1;
+             else
+               {
+                 if (opterr)
+                   {
+                     if (argv[optind - 1][1] == '-')
+                       /* --option */
+                       fprintf (stderr,
+                                "%s: option `--%s' doesn't allow an argument\n",
+                                argv[0], pfound->name);
+                     else
+                       /* +option or -option */
+                       fprintf (stderr,
+                            "%s: option `%c%s' doesn't allow an argument\n",
+                            argv[0], argv[optind - 1][0], pfound->name);
+                   }
+                 nextchar += strlen (nextchar);
+                 return '?';
+               }
+           }
+         else if (pfound->has_arg == 1)
+           {
+             if (optind < argc)
+               optarg = argv[optind++];
+             else
+               {
+                 if (opterr)
+                   fprintf (stderr, "%s: option `%s' requires an argument\n",
+                            argv[0], argv[optind - 1]);
+                 nextchar += strlen (nextchar);
+                 return optstring[0] == ':' ? ':' : '?';
+               }
+           }
+         nextchar += strlen (nextchar);
+         if (longind != NULL)
+           *longind = option_index;
+         if (pfound->flag)
+           {
+             *(pfound->flag) = pfound->val;
+             return 0;
+           }
+         return pfound->val;
+       }
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+        or the option starts with '--' or is not a valid short
+        option, then it's an error.
+        Otherwise interpret it as a short option.  */
+      if (!long_only || argv[optind][1] == '-'
+         || my_index (optstring, *nextchar) == NULL)
+       {
+         if (opterr)
+           {
+             if (argv[optind][1] == '-')
+               /* --option */
+               fprintf (stderr, "%s: unrecognized option `--%s'\n",
+                        argv[0], nextchar);
+             else
+               /* +option or -option */
+               fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+                        argv[0], argv[optind][0], nextchar);
+           }
+         nextchar = (char *) "";
+         optind++;
+         return '?';
+       }
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *nextchar++;
+    char *temp = my_index (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*nextchar == '\0')
+      ++optind;
+
+    if (temp == NULL || c == ':')
+      {
+       if (opterr)
+         {
+           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 '?';
+      }
+    if (temp[1] == ':')
+      {
+       if (temp[2] == ':')
+         {
+           /* This is an option that accepts an argument optionally.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               optind++;
+             }
+           else
+             optarg = NULL;
+           nextchar = NULL;
+         }
+       else
+         {
+           /* This is an option that requires an argument.  */
+           if (*nextchar != '\0')
+             {
+               optarg = nextchar;
+               /* If we end this ARGV-element by taking the rest as an arg,
+                  we must advance to the next element now.  */
+               optind++;
+             }
+           else if (optind == argc)
+             {
+               if (opterr)
+                 {
+                   /* 1003.2 specifies the format of this message.  */
+                   fprintf (stderr, "%s: option requires an argument -- %c\n",
+                            argv[0], c);
+                 }
+               optopt = c;
+               if (optstring[0] == ':')
+                 c = ':';
+               else
+                 c = '?';
+             }
+           else
+             /* We already incremented `optind' once;
+                increment it again when taking next ARGV-elt as argument.  */
+             optarg = argv[optind++];
+           nextchar = NULL;
+         }
+      }
+    return c;
+  }
+}
+
+int
+getopt (argc, argv, optstring)
+     int argc;
+     char *const *argv;
+     const char *optstring;
+{
+  return _getopt_internal (argc, argv, optstring,
+                          (const struct option *) 0,
+                          (int *) 0,
+                          0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+\f
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == EOF)
+       break;
+
+      switch (c)
+       {
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_optind != 0 && digit_optind != this_option_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_optind = this_option_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+       printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt1.c b/lib/getopt1.c
new file mode 100644 (file)
index 0000000..de8e2ad
--- /dev/null
@@ -0,0 +1,184 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
+       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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+\f
+#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.  */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef        NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+     int argc;
+     char *const *argv;
+     const char *options;
+     const struct option *long_options;
+     int *opt_index;
+{
+  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
+\f
+#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 == EOF)
+       break;
+
+      switch (c)
+       {
+       case 0:
+         printf ("option %s", long_options[option_index].name);
+         if (optarg)
+           printf (" with arg %s", optarg);
+         printf ("\n");
+         break;
+
+       case '0':
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':
+         if (digit_optind != 0 && digit_optind != this_option_optind)
+           printf ("digits occur in two different argv-elements.\n");
+         digit_optind = this_option_optind;
+         printf ("option %c\n", c);
+         break;
+
+       case 'a':
+         printf ("option a\n");
+         break;
+
+       case 'b':
+         printf ("option b\n");
+         break;
+
+       case 'c':
+         printf ("option c with value `%s'\n", optarg);
+         break;
+
+       case 'd':
+         printf ("option d with value `%s'\n", optarg);
+         break;
+
+       case '?':
+         break;
+
+       default:
+         printf ("?? getopt returned character code 0%o ??\n", c);
+       }
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+       printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/number.c b/lib/number.c
new file mode 100644 (file)
index 0000000..240f653
--- /dev/null
@@ -0,0 +1,1794 @@
+/* number.c: Implements arbitrary precision numbers. */
+/*
+    Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 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 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; see the file COPYING.  If not, write to:
+
+      The Free Software Foundation, Inc.
+      59 Temple Place, Suite 330
+      Boston, MA 02111-1307 USA.
+
+
+    You may contact the author by:
+       e-mail:  philnelson@acm.org
+      us-mail:  Philip A. Nelson
+                Computer Science Department, 9062
+                Western Washington University
+                Bellingham, WA 98226-9062
+       
+*************************************************************************/
+
+#include <stdio.h>
+#include <config.h>
+#include <number.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>/* Prototypes needed for external utility routines. */
+#include <string.h>
+
+#define bc_rt_warn rt_warn
+#define bc_rt_error rt_error
+#define bc_out_of_memory out_of_memory
+
+_PROTOTYPE(void rt_warn, (char *mesg ,...));
+_PROTOTYPE(void rt_error, (char *mesg ,...));
+_PROTOTYPE(void out_of_memory, (void));
+
+/* Storage used for special numbers. */
+bc_num _zero_;
+bc_num _one_;
+bc_num _two_;
+
+static bc_num _bc_Free_list = NULL;
+
+/* new_num allocates a number and sets fields to known values. */
+
+bc_num
+bc_new_num (length, scale)
+     int length, scale;
+{
+  bc_num temp;
+
+  if (_bc_Free_list != NULL) {
+    temp = _bc_Free_list;
+    _bc_Free_list = temp->n_next;
+  } else {
+    temp = (bc_num) malloc (sizeof(bc_struct));
+    if (temp == NULL) bc_out_of_memory ();
+  }
+  temp->n_sign = PLUS;
+  temp->n_len = length;
+  temp->n_scale = scale;
+  temp->n_refs = 1;
+  temp->n_ptr = (char *) malloc (length+scale);
+  if (temp->n_ptr == NULL) bc_out_of_memory();
+  temp->n_value = temp->n_ptr;
+  memset (temp->n_ptr, 0, length+scale);
+  return temp;
+}
+
+/* "Frees" a bc_num NUM.  Actually decreases reference count and only
+   frees the storage if reference count is zero. */
+
+void
+bc_free_num (num)
+    bc_num *num;
+{
+  if (*num == NULL) return;
+  (*num)->n_refs--;
+  if ((*num)->n_refs == 0) {
+    if ((*num)->n_ptr)
+      free ((*num)->n_ptr);
+    (*num)->n_next = _bc_Free_list;
+    _bc_Free_list = *num;
+  }
+  *num = NULL;
+}
+
+
+/* Intitialize the number package! */
+
+void
+bc_init_numbers ()
+{
+  _zero_ = bc_new_num (1,0);
+  _one_  = bc_new_num (1,0);
+  _one_->n_value[0] = 1;
+  _two_  = bc_new_num (1,0);
+  _two_->n_value[0] = 2;
+}
+
+
+/* Make a copy of a number!  Just increments the reference count! */
+
+bc_num
+bc_copy_num (num)
+     bc_num num;
+{
+  num->n_refs++;
+  return num;
+}
+
+
+/* Initialize a number NUM by making it a copy of zero. */
+
+void
+bc_init_num (num)
+     bc_num *num;
+{
+  *num = bc_copy_num (_zero_);
+}
+
+/* For many things, we may have leading zeros in a number NUM.
+   _bc_rm_leading_zeros just moves the data "value" pointer to the
+   correct place and adjusts the length. */
+
+static void
+_bc_rm_leading_zeros (num)
+     bc_num num;
+{
+  /* We can move n_value to point to the first non zero digit! */
+  while (*num->n_value == 0 && num->n_len > 1) {
+    num->n_value++;
+    num->n_len--;
+  }
+}
+
+
+/* Compare two bc numbers.  Return value is 0 if equal, -1 if N1 is less
+   than N2 and +1 if N1 is greater than N2.  If USE_SIGN is false, just
+   compare the magnitudes. */
+
+static int
+_bc_do_compare (n1, n2, use_sign, ignore_last)
+     bc_num n1, n2;
+     int use_sign;
+     int ignore_last;
+{
+  char *n1ptr, *n2ptr;
+  int  count;
+
+  /* First, compare signs. */
+  if (use_sign && n1->n_sign != n2->n_sign)
+    {
+      if (n1->n_sign == PLUS)
+       return (1);     /* Positive N1 > Negative N2 */
+      else
+       return (-1);    /* Negative N1 < Positive N1 */
+    }
+
+  /* Now compare the magnitude. */
+  if (n1->n_len != n2->n_len)
+    {
+      if (n1->n_len > n2->n_len)
+       {
+         /* Magnitude of n1 > n2. */
+         if (!use_sign || n1->n_sign == PLUS)
+           return (1);
+         else
+           return (-1);
+       }
+      else
+       {
+         /* Magnitude of n1 < n2. */
+         if (!use_sign || n1->n_sign == PLUS)
+           return (-1);
+         else
+           return (1);
+       }
+    }
+
+  /* If we get here, they have the same number of integer digits.
+     check the integer part and the equal length part of the fraction. */
+  count = n1->n_len + MIN (n1->n_scale, n2->n_scale);
+  n1ptr = n1->n_value;
+  n2ptr = n2->n_value;
+
+  while ((count > 0) && (*n1ptr == *n2ptr))
+    {
+      n1ptr++;
+      n2ptr++;
+      count--;
+    }
+  if (ignore_last && count == 1 && n1->n_scale == n2->n_scale)
+    return (0);
+  if (count != 0)
+    {
+      if (*n1ptr > *n2ptr)
+       {
+         /* Magnitude of n1 > n2. */
+         if (!use_sign || n1->n_sign == PLUS)
+           return (1);
+         else
+           return (-1);
+       }
+      else
+       {
+         /* Magnitude of n1 < n2. */
+         if (!use_sign || n1->n_sign == PLUS)
+           return (-1);
+         else
+           return (1);
+       }
+    }
+
+  /* They are equal up to the last part of the equal part of the fraction. */
+  if (n1->n_scale != n2->n_scale)
+    {
+      if (n1->n_scale > n2->n_scale)
+       {
+         for (count = n1->n_scale-n2->n_scale; count>0; count--)
+           if (*n1ptr++ != 0)
+             {
+               /* Magnitude of n1 > n2. */
+               if (!use_sign || n1->n_sign == PLUS)
+                 return (1);
+               else
+                 return (-1);
+             }
+       }
+      else
+       {
+         for (count = n2->n_scale-n1->n_scale; count>0; count--)
+           if (*n2ptr++ != 0)
+             {
+               /* Magnitude of n1 < n2. */
+               if (!use_sign || n1->n_sign == PLUS)
+                 return (-1);
+               else
+                 return (1);
+             }
+       }
+    }
+
+  /* They must be equal! */
+  return (0);
+}
+
+
+/* This is the "user callable" routine to compare numbers N1 and N2. */
+
+int
+bc_compare (n1, n2)
+     bc_num n1, n2;
+{
+  return _bc_do_compare (n1, n2, TRUE, FALSE);
+}
+
+/* In some places we need to check if the number is negative. */
+
+char
+bc_is_neg (num)
+     bc_num num;
+{
+  return num->n_sign == MINUS;
+}
+
+/* In some places we need to check if the number NUM is zero. */
+
+char
+bc_is_zero (num)
+     bc_num num;
+{
+  int  count;
+  char *nptr;
+
+  /* Quick check. */
+  if (num == _zero_) return TRUE;
+
+  /* Initialize */
+  count = num->n_len + num->n_scale;
+  nptr = num->n_value;
+
+  /* The check */
+  while ((count > 0) && (*nptr++ == 0)) count--;
+
+  if (count != 0)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/* In some places we need to check if the number NUM is almost zero.
+   Specifically, all but the last digit is 0 and the last digit is 1.
+   Last digit is defined by scale. */
+
+char
+bc_is_near_zero (num, scale)
+     bc_num num;
+     int scale;
+{
+  int  count;
+  char *nptr;
+
+  /* Error checking */
+  if (scale > num->n_scale)
+    scale = num->n_scale;
+
+  /* Initialize */
+  count = num->n_len + scale;
+  nptr = num->n_value;
+
+  /* The check */
+  while ((count > 0) && (*nptr++ == 0)) count--;
+
+  if (count != 0 && (count != 1 || *--nptr != 1))
+    return FALSE;
+  else
+    return TRUE;
+}
+
+
+/* Perform addition: N1 is added to N2 and the value is
+   returned.  The signs of N1 and N2 are ignored.
+   SCALE_MIN is to set the minimum scale of the result. */
+
+static bc_num
+_bc_do_add (n1, n2, scale_min)
+     bc_num n1, n2;
+     int scale_min;
+{
+  bc_num sum;
+  int sum_scale, sum_digits;
+  char *n1ptr, *n2ptr, *sumptr;
+  int carry, n1bytes, n2bytes;
+  int count;
+
+  /* Prepare sum. */
+  sum_scale = MAX (n1->n_scale, n2->n_scale);
+  sum_digits = MAX (n1->n_len, n2->n_len) + 1;
+  sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min));
+
+  /* Zero extra digits made by scale_min. */
+  if (scale_min > sum_scale)
+    {
+      sumptr = (char *) (sum->n_value + sum_scale + sum_digits);
+      for (count = scale_min - sum_scale; count > 0; count--)
+       *sumptr++ = 0;
+    }
+
+  /* Start with the fraction part.  Initialize the pointers. */
+  n1bytes = n1->n_scale;
+  n2bytes = n2->n_scale;
+  n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1);
+  n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1);
+  sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1);
+
+  /* Add the fraction part.  First copy the longer fraction.*/
+  if (n1bytes != n2bytes)
+    {
+      if (n1bytes > n2bytes)
+       while (n1bytes>n2bytes)
+         { *sumptr-- = *n1ptr--; n1bytes--;}
+      else
+       while (n2bytes>n1bytes)
+         { *sumptr-- = *n2ptr--; n2bytes--;}
+    }
+
+  /* Now add the remaining fraction part and equal size integer parts. */
+  n1bytes += n1->n_len;
+  n2bytes += n2->n_len;
+  carry = 0;
+  while ((n1bytes > 0) && (n2bytes > 0))
+    {
+      *sumptr = *n1ptr-- + *n2ptr-- + carry;
+      if (*sumptr > (BASE-1))
+       {
+          carry = 1;
+          *sumptr -= BASE;
+       }
+      else
+       carry = 0;
+      sumptr--;
+      n1bytes--;
+      n2bytes--;
+    }
+
+  /* Now add carry the longer integer part. */
+  if (n1bytes == 0)
+    { n1bytes = n2bytes; n1ptr = n2ptr; }
+  while (n1bytes-- > 0)
+    {
+      *sumptr = *n1ptr-- + carry;
+      if (*sumptr > (BASE-1))
+       {
+          carry = 1;
+          *sumptr -= BASE;
+        }
+      else
+       carry = 0;
+      sumptr--;
+    }
+
+  /* Set final carry. */
+  if (carry == 1)
+    *sumptr += 1;
+
+  /* Adjust sum and return. */
+  _bc_rm_leading_zeros (sum);
+  return sum;
+}
+
+
+/* Perform subtraction: N2 is subtracted from N1 and the value is
+   returned.  The signs of N1 and N2 are ignored.  Also, N1 is
+   assumed to be larger than N2.  SCALE_MIN is the minimum scale
+   of the result. */
+
+static bc_num
+_bc_do_sub (n1, n2, scale_min)
+     bc_num n1, n2;
+     int scale_min;
+{
+  bc_num diff;
+  int diff_scale, diff_len;
+  int min_scale, min_len;
+  char *n1ptr, *n2ptr, *diffptr;
+  int borrow, count, val;
+
+  /* Allocate temporary storage. */
+  diff_len = MAX (n1->n_len, n2->n_len);
+  diff_scale = MAX (n1->n_scale, n2->n_scale);
+  min_len = MIN  (n1->n_len, n2->n_len);
+  min_scale = MIN (n1->n_scale, n2->n_scale);
+  diff = bc_new_num (diff_len, MAX(diff_scale, scale_min));
+
+  /* Zero extra digits made by scale_min. */
+  if (scale_min > diff_scale)
+    {
+      diffptr = (char *) (diff->n_value + diff_len + diff_scale);
+      for (count = scale_min - diff_scale; count > 0; count--)
+       *diffptr++ = 0;
+    }
+
+  /* Initialize the subtract. */
+  n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1);
+  n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1);
+  diffptr = (char *) (diff->n_value + diff_len + diff_scale -1);
+
+  /* Subtract the numbers. */
+  borrow = 0;
+
+  /* Take care of the longer scaled number. */
+  if (n1->n_scale != min_scale)
+    {
+      /* n1 has the longer scale */
+      for (count = n1->n_scale - min_scale; count > 0; count--)
+       *diffptr-- = *n1ptr--;
+    }
+  else
+    {
+      /* n2 has the longer scale */
+      for (count = n2->n_scale - min_scale; count > 0; count--)
+       {
+         val = - *n2ptr-- - borrow;
+         if (val < 0)
+           {
+             val += BASE;
+             borrow = 1;
+           }
+         else
+           borrow = 0;
+         *diffptr-- = val;
+       }
+    }
+
+  /* Now do the equal length scale and integer parts. */
+
+  for (count = 0; count < min_len + min_scale; count++)
+    {
+      val = *n1ptr-- - *n2ptr-- - borrow;
+      if (val < 0)
+       {
+         val += BASE;
+         borrow = 1;
+       }
+      else
+       borrow = 0;
+      *diffptr-- = val;
+    }
+
+  /* If n1 has more digits then n2, we now do that subtract. */
+  if (diff_len != min_len)
+    {
+      for (count = diff_len - min_len; count > 0; count--)
+       {
+         val = *n1ptr-- - borrow;
+         if (val < 0)
+           {
+             val += BASE;
+             borrow = 1;
+           }
+         else
+           borrow = 0;
+         *diffptr-- = val;
+       }
+    }
+
+  /* Clean up and return. */
+  _bc_rm_leading_zeros (diff);
+  return diff;
+}
+
+
+/* Here is the full subtract routine that takes care of negative numbers.
+   N2 is subtracted from N1 and the result placed in RESULT.  SCALE_MIN
+   is the minimum scale for the result. */
+
+void
+bc_sub (n1, n2, result, scale_min)
+     bc_num n1, n2, *result;
+     int scale_min;
+{
+  bc_num diff = NULL;
+  int cmp_res;
+  int res_scale;
+
+  if (n1->n_sign != n2->n_sign)
+    {
+      diff = _bc_do_add (n1, n2, scale_min);
+      diff->n_sign = n1->n_sign;
+    }
+  else
+    {
+      /* subtraction must be done. */
+      /* Compare magnitudes. */
+      cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE);
+      switch (cmp_res)
+       {
+       case -1:
+         /* n1 is less than n2, subtract n1 from n2. */
+         diff = _bc_do_sub (n2, n1, scale_min);
+         diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
+         break;
+       case  0:
+         /* They are equal! return zero! */
+         res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
+         diff = bc_new_num (1, res_scale);
+         memset (diff->n_value, 0, res_scale+1);
+         break;
+       case  1:
+         /* n2 is less than n1, subtract n2 from n1. */
+         diff = _bc_do_sub (n1, n2, scale_min);
+         diff->n_sign = n1->n_sign;
+         break;
+       }
+    }
+
+  /* Clean up and return. */
+  bc_free_num (result);
+  *result = diff;
+}
+
+
+/* Here is the full add routine that takes care of negative numbers.
+   N1 is added to N2 and the result placed into RESULT.  SCALE_MIN
+   is the minimum scale for the result. */
+
+void
+bc_add (n1, n2, result, scale_min)
+     bc_num n1, n2, *result;
+     int scale_min;
+{
+  bc_num sum = NULL;
+  int cmp_res;
+  int res_scale;
+
+  if (n1->n_sign == n2->n_sign)
+    {
+      sum = _bc_do_add (n1, n2, scale_min);
+      sum->n_sign = n1->n_sign;
+    }
+  else
+    {
+      /* subtraction must be done. */
+      cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE);  /* Compare magnitudes. */
+      switch (cmp_res)
+       {
+       case -1:
+         /* n1 is less than n2, subtract n1 from n2. */
+         sum = _bc_do_sub (n2, n1, scale_min);
+         sum->n_sign = n2->n_sign;
+         break;
+       case  0:
+         /* They are equal! return zero with the correct scale! */
+         res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
+         sum = bc_new_num (1, res_scale);
+         memset (sum->n_value, 0, res_scale+1);
+         break;
+       case  1:
+         /* n2 is less than n1, subtract n2 from n1. */
+         sum = _bc_do_sub (n1, n2, scale_min);
+         sum->n_sign = n1->n_sign;
+       }
+    }
+
+  /* Clean up and return. */
+  bc_free_num (result);
+  *result = sum;
+}
+
+/* Recursive vs non-recursive multiply crossover ranges. */
+#if defined(MULDIGITS)
+#include "muldigits.h"
+#else
+#define MUL_BASE_DIGITS 80
+#endif
+
+int mul_base_digits = MUL_BASE_DIGITS;
+#define MUL_SMALL_DIGITS mul_base_digits/4
+
+/* Multiply utility routines */
+
+static bc_num
+new_sub_num (length, scale, value)
+     int length, scale;
+     char *value;
+{
+  bc_num temp;
+
+  if (_bc_Free_list != NULL) {
+    temp = _bc_Free_list;
+    _bc_Free_list = temp->n_next;
+  } else {
+    temp = (bc_num) malloc (sizeof(bc_struct));
+    if (temp == NULL) bc_out_of_memory ();
+  }
+  temp->n_sign = PLUS;
+  temp->n_len = length;
+  temp->n_scale = scale;
+  temp->n_refs = 1;
+  temp->n_ptr = NULL;
+  temp->n_value = value;
+  return temp;
+}
+
+static void
+_bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod,
+             int full_scale)
+{
+  char *n1ptr, *n2ptr, *pvptr;
+  char *n1end, *n2end;         /* To the end of n1 and n2. */
+  int indx, sum, prodlen;
+
+  prodlen = n1len+n2len+1;
+
+  *prod = bc_new_num (prodlen, 0);
+
+  n1end = (char *) (n1->n_value + n1len - 1);
+  n2end = (char *) (n2->n_value + n2len - 1);
+  pvptr = (char *) ((*prod)->n_value + prodlen - 1);
+  sum = 0;
+
+  /* Here is the loop... */
+  for (indx = 0; indx < prodlen-1; indx++)
+    {
+      n1ptr = (char *) (n1end - MAX(0, indx-n2len+1));
+      n2ptr = (char *) (n2end - MIN(indx, n2len-1));
+      while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
+       sum += *n1ptr-- * *n2ptr++;
+      *pvptr-- = sum % BASE;
+      sum = sum / BASE;
+    }
+  *pvptr = sum;
+}
+
+
+/* A special adder/subtractor for the recursive divide and conquer
+   multiply algorithm.  Note: if sub is called, accum must
+   be larger that what is being subtracted.  Also, accum and val
+   must have n_scale = 0.  (e.g. they must look like integers. *) */
+static void
+_bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub)
+{
+  signed char *accp, *valp;
+  int  count, carry;
+
+  count = val->n_len;
+  if (val->n_value[0] == 0)
+    count--;
+  assert (accum->n_len+accum->n_scale >= shift+count);
+  
+  /* Set up pointers and others */
+  accp = (signed char *)(accum->n_value +
+                        accum->n_len + accum->n_scale - shift - 1);
+  valp = (signed char *)(val->n_value + val->n_len - 1);
+  carry = 0;
+
+  if (sub) {
+    /* Subtraction, carry is really borrow. */
+    while (count--) {
+      *accp -= *valp-- + carry;
+      if (*accp < 0) {
+       carry = 1;
+        *accp-- += BASE;
+      } else {
+       carry = 0;
+       accp--;
+      }
+    }
+    while (carry) {
+      *accp -= carry;
+      if (*accp < 0)
+       *accp-- += BASE;
+      else
+       carry = 0;
+    }
+  } else {
+    /* Addition */
+    while (count--) {
+      *accp += *valp-- + carry;
+      if (*accp > (BASE-1)) {
+       carry = 1;
+        *accp-- -= BASE;
+      } else {
+       carry = 0;
+       accp--;
+      }
+    }
+    while (carry) {
+      *accp += carry;
+      if (*accp > (BASE-1))
+       *accp-- -= BASE;
+      else
+       carry = 0;
+    }
+  }
+}
+
+/* Recursive divide and conquer multiply algorithm.  
+   Based on 
+   Let u = u0 + u1*(b^n)
+   Let v = v0 + v1*(b^n)
+   Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0
+
+   B is the base of storage, number of digits in u1,u0 close to equal.
+*/
+static void
+_bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
+            int full_scale)
+{ 
+  bc_num u0, u1, v0, v1;
+  int u0len, v0len;
+  bc_num m1, m2, m3, d1, d2;
+  int n, prodlen, m1zero;
+  int d1len, d2len;
+
+  /* Base case? */
+  if ((ulen+vlen) < mul_base_digits
+      || ulen < MUL_SMALL_DIGITS
+      || vlen < MUL_SMALL_DIGITS ) {
+    _bc_simp_mul (u, ulen, v, vlen, prod, full_scale);
+    return;
+  }
+
+  /* Calculate n -- the u and v split point in digits. */
+  n = (MAX(ulen, vlen)+1) / 2;
+
+  /* Split u and v. */
+  if (ulen < n) {
+    u1 = bc_copy_num (_zero_);
+    u0 = new_sub_num (ulen,0, u->n_value);
+  } else {
+    u1 = new_sub_num (ulen-n, 0, u->n_value);
+    u0 = new_sub_num (n, 0, u->n_value+ulen-n);
+  }
+  if (vlen < n) {
+    v1 = bc_copy_num (_zero_);
+    v0 = new_sub_num (vlen,0, v->n_value);
+  } else {
+    v1 = new_sub_num (vlen-n, 0, v->n_value);
+    v0 = new_sub_num (n, 0, v->n_value+vlen-n);
+    }
+  _bc_rm_leading_zeros (u1);
+  _bc_rm_leading_zeros (u0);
+  u0len = u0->n_len;
+  _bc_rm_leading_zeros (v1);
+  _bc_rm_leading_zeros (v0);
+  v0len = v0->n_len;
+
+  m1zero = bc_is_zero(u1) || bc_is_zero(v1);
+
+  /* Calculate sub results ... */
+
+  bc_init_num(&d1);
+  bc_init_num(&d2);
+  bc_sub (u1, u0, &d1, 0);
+  d1len = d1->n_len;
+  bc_sub (v0, v1, &d2, 0);
+  d2len = d2->n_len;
+
+
+  /* Do recursive multiplies and shifted adds. */
+  if (m1zero)
+    m1 = bc_copy_num (_zero_);
+  else
+    _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0);
+
+  if (bc_is_zero(d1) || bc_is_zero(d2))
+    m2 = bc_copy_num (_zero_);
+  else
+    _bc_rec_mul (d1, d1len, d2, d2len, &m2, 0);
+
+  if (bc_is_zero(u0) || bc_is_zero(v0))
+    m3 = bc_copy_num (_zero_);
+  else
+    _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0);
+
+  /* Initialize product */
+  prodlen = ulen+vlen+1;
+  *prod = bc_new_num(prodlen, 0);
+
+  if (!m1zero) {
+    _bc_shift_addsub (*prod, m1, 2*n, 0);
+    _bc_shift_addsub (*prod, m1, n, 0);
+  }
+  _bc_shift_addsub (*prod, m3, n, 0);
+  _bc_shift_addsub (*prod, m3, 0, 0);
+  _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign);
+
+  /* Now clean up! */
+  bc_free_num (&u1);
+  bc_free_num (&u0);
+  bc_free_num (&v1);
+  bc_free_num (&m1);
+  bc_free_num (&v0);
+  bc_free_num (&m2);
+  bc_free_num (&m3);
+  bc_free_num (&d1);
+  bc_free_num (&d2);
+}
+
+/* The multiply routine.  N2 times N1 is put int PROD with the scale of
+   the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)).
+   */
+
+void
+bc_multiply (n1, n2, prod, scale)
+     bc_num n1, n2, *prod;
+     int scale;
+{
+  bc_num pval; 
+  int len1, len2;
+  int full_scale, prod_scale;
+
+  /* Initialize things. */
+  len1 = n1->n_len + n1->n_scale;
+  len2 = n2->n_len + n2->n_scale;
+  full_scale = n1->n_scale + n2->n_scale;
+  prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
+
+  /* Do the multiply */
+  _bc_rec_mul (n1, len1, n2, len2, &pval, full_scale);
+
+  /* Assign to prod and clean up the number. */
+  pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
+  pval->n_value = pval->n_ptr;
+  pval->n_len = len2 + len1 + 1 - full_scale;
+  pval->n_scale = prod_scale;
+  _bc_rm_leading_zeros (pval);
+  if (bc_is_zero (pval))
+    pval->n_sign = PLUS;
+  bc_free_num (prod);
+  *prod = pval;
+}
+
+/* Some utility routines for the divide:  First a one digit multiply.
+   NUM (with SIZE digits) is multiplied by DIGIT and the result is
+   placed into RESULT.  It is written so that NUM and RESULT can be
+   the same pointers.  */
+
+static void
+_one_mult (num, size, digit, result)
+     unsigned char *num;
+     int size, digit;
+     unsigned char *result;
+{
+  int carry, value;
+  unsigned char *nptr, *rptr;
+
+  if (digit == 0)
+    memset (result, 0, size);
+  else
+    {
+      if (digit == 1)
+       memcpy (result, num, size);
+      else
+       {
+         /* Initialize */
+         nptr = (unsigned char *) (num+size-1);
+         rptr = (unsigned char *) (result+size-1);
+         carry = 0;
+
+         while (size-- > 0)
+           {
+             value = *nptr-- * digit + carry;
+             *rptr-- = value % BASE;
+             carry = value / BASE;
+           }
+
+         if (carry != 0) *rptr = carry;
+       }
+    }
+}
+
+
+/* The full division routine. This computes N1 / N2.  It returns
+   0 if the division is ok and the result is in QUOT.  The number of
+   digits after the decimal point is SCALE. It returns -1 if division
+   by zero is tried.  The algorithm is found in Knuth Vol 2. p237. */
+
+int
+bc_divide (n1, n2, quot, scale)
+     bc_num n1, n2, *quot;
+     int scale;
+{
+  bc_num qval;
+  unsigned char *num1, *num2;
+  unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
+  int  scale1, val;
+  unsigned int  len1, len2, scale2, qdigits, extra, count;
+  unsigned int  qdig, qguess, borrow, carry;
+  unsigned char *mval;
+  char zero;
+  unsigned int  norm;
+
+  /* Test for divide by zero. */
+  if (bc_is_zero (n2)) return -1;
+
+  /* Test for divide by 1.  If it is we must truncate. */
+  if (n2->n_scale == 0)
+    {
+      if (n2->n_len == 1 && *n2->n_value == 1)
+       {
+         qval = bc_new_num (n1->n_len, scale);
+         qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS);
+         memset (&qval->n_value[n1->n_len],0,scale);
+         memcpy (qval->n_value, n1->n_value,
+                 n1->n_len + MIN(n1->n_scale,scale));
+         bc_free_num (quot);
+         *quot = qval;
+       }
+    }
+
+  /* Set up the divide.  Move the decimal point on n1 by n2's scale.
+     Remember, zeros on the end of num2 are wasted effort for dividing. */
+  scale2 = n2->n_scale;
+  n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1;
+  while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--;
+
+  len1 = n1->n_len + scale2;
+  scale1 = n1->n_scale - scale2;
+  if (scale1 < scale)
+    extra = scale - scale1;
+  else
+    extra = 0;
+  num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2);
+  if (num1 == NULL) bc_out_of_memory();
+  memset (num1, 0, n1->n_len+n1->n_scale+extra+2);
+  memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale);
+
+  len2 = n2->n_len + scale2;
+  num2 = (unsigned char *) malloc (len2+1);
+  if (num2 == NULL) bc_out_of_memory();
+  memcpy (num2, n2->n_value, len2);
+  *(num2+len2) = 0;
+  n2ptr = num2;
+  while (*n2ptr == 0)
+    {
+      n2ptr++;
+      len2--;
+    }
+
+  /* Calculate the number of quotient digits. */
+  if (len2 > len1+scale)
+    {
+      qdigits = scale+1;
+      zero = TRUE;
+    }
+  else
+    {
+      zero = FALSE;
+      if (len2>len1)
+       qdigits = scale+1;      /* One for the zero integer part. */
+      else
+       qdigits = len1-len2+scale+1;
+    }
+
+  /* Allocate and zero the storage for the quotient. */
+  qval = bc_new_num (qdigits-scale,scale);
+  memset (qval->n_value, 0, qdigits);
+
+  /* Allocate storage for the temporary storage mval. */
+  mval = (unsigned char *) malloc (len2+1);
+  if (mval == NULL) bc_out_of_memory ();
+
+  /* Now for the full divide algorithm. */
+  if (!zero)
+    {
+      /* Normalize */
+      norm =  10 / ((int)*n2ptr + 1);
+      if (norm != 1)
+       {
+         _one_mult (num1, len1+scale1+extra+1, norm, num1);
+         _one_mult (n2ptr, len2, norm, n2ptr);
+       }
+
+      /* Initialize divide loop. */
+      qdig = 0;
+      if (len2 > len1)
+       qptr = (unsigned char *) qval->n_value+len2-len1;
+      else
+       qptr = (unsigned char *) qval->n_value;
+
+      /* Loop */
+      while (qdig <= len1+scale-len2)
+       {
+         /* Calculate the quotient digit guess. */
+         if (*n2ptr == num1[qdig])
+           qguess = 9;
+         else
+           qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr;
+
+         /* Test qguess. */
+         if (n2ptr[1]*qguess >
+             (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
+              + num1[qdig+2])
+           {
+             qguess--;
+             /* And again. */
+             if (n2ptr[1]*qguess >
+                 (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10
+                 + num1[qdig+2])
+               qguess--;
+           }
+
+         /* Multiply and subtract. */
+         borrow = 0;
+         if (qguess != 0)
+           {
+             *mval = 0;
+             _one_mult (n2ptr, len2, qguess, mval+1);
+             ptr1 = (unsigned char *) num1+qdig+len2;
+             ptr2 = (unsigned char *) mval+len2;
+             for (count = 0; count < len2+1; count++)
+               {
+                 val = (int) *ptr1 - (int) *ptr2-- - borrow;
+                 if (val < 0)
+                   {
+                     val += 10;
+                     borrow = 1;
+                   }
+                 else
+                   borrow = 0;
+                 *ptr1-- = val;
+               }
+           }
+
+         /* Test for negative result. */
+         if (borrow == 1)
+           {
+             qguess--;
+             ptr1 = (unsigned char *) num1+qdig+len2;
+             ptr2 = (unsigned char *) n2ptr+len2-1;
+             carry = 0;
+             for (count = 0; count < len2; count++)
+               {
+                 val = (int) *ptr1 + (int) *ptr2-- + carry;
+                 if (val > 9)
+                   {
+                     val -= 10;
+                     carry = 1;
+                   }
+                 else
+                   carry = 0;
+                 *ptr1-- = val;
+               }
+             if (carry == 1) *ptr1 = (*ptr1 + 1) % 10;
+           }
+
+         /* We now know the quotient digit. */
+         *qptr++ =  qguess;
+         qdig++;
+       }
+    }
+
+  /* Clean up and return the number. */
+  qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
+  if (bc_is_zero (qval)) qval->n_sign = PLUS;
+  _bc_rm_leading_zeros (qval);
+  bc_free_num (quot);
+  *quot = qval;
+
+  /* Clean up temporary storage. */
+  free (mval);
+  free (num1);
+  free (num2);
+
+  return 0;    /* Everything is OK. */
+}
+
+
+/* Division *and* modulo for numbers.  This computes both NUM1 / NUM2 and
+   NUM1 % NUM2  and puts the results in QUOT and REM, except that if QUOT
+   is NULL then that store will be omitted.
+ */
+
+int
+bc_divmod (num1, num2, quot, rem, scale)
+     bc_num num1, num2, *quot, *rem;
+     int scale;
+{
+  bc_num quotient = NULL;
+  bc_num temp;
+  int rscale;
+
+  /* Check for correct numbers. */
+  if (bc_is_zero (num2)) return -1;
+
+  /* Calculate final scale. */
+  rscale = MAX (num1->n_scale, num2->n_scale+scale);
+  bc_init_num(&temp);
+
+  /* Calculate it. */
+  bc_divide (num1, num2, &temp, scale);
+  if (quot)
+    quotient = bc_copy_num (temp);
+  bc_multiply (temp, num2, &temp, rscale);
+  bc_sub (num1, temp, rem, rscale);
+  bc_free_num (&temp);
+
+  if (quot)
+    {
+      bc_free_num (quot);
+      *quot = quotient;
+    }
+
+  return 0;    /* Everything is OK. */
+}
+
+
+/* Modulo for numbers.  This computes NUM1 % NUM2  and puts the
+   result in RESULT.   */
+
+int
+bc_modulo (num1, num2, result, scale)
+     bc_num num1, num2, *result;
+     int scale;
+{
+  return bc_divmod (num1, num2, NULL, result, scale);
+}
+
+/* Raise BASE to the EXPO power, reduced modulo MOD.  The result is
+   placed in RESULT.  If a EXPO is not an integer,
+   only the integer part is used.  */
+
+int
+bc_raisemod (base, expo, mod, result, scale)
+     bc_num base, expo, mod, *result;
+     int scale;
+{
+  bc_num power, exponent, parity, temp;
+  int rscale;
+
+  /* Check for correct numbers. */
+  if (bc_is_zero(mod)) return -1;
+  if (bc_is_neg(expo)) return -1;
+
+  /* Set initial values.  */
+  power = bc_copy_num (base);
+  exponent = bc_copy_num (expo);
+  temp = bc_copy_num (_one_);
+  bc_init_num(&parity);
+
+  /* Check the base for scale digits. */
+  if (base->n_scale != 0)
+      bc_rt_warn ("non-zero scale in base");
+
+  /* Check the exponent for scale digits. */
+  if (exponent->n_scale != 0)
+    {
+      bc_rt_warn ("non-zero scale in exponent");
+      bc_divide (exponent, _one_, &exponent, 0); /*truncate */
+    }
+
+  /* Check the modulus for scale digits. */
+  if (mod->n_scale != 0)
+      bc_rt_warn ("non-zero scale in modulus");
+
+  /* Do the calculation. */
+  rscale = MAX(scale, base->n_scale);
+  while ( !bc_is_zero(exponent) )
+    {
+      (void) bc_divmod (exponent, _two_, &exponent, &parity, 0);
+      if ( !bc_is_zero(parity) )
+       {
+         bc_multiply (temp, power, &temp, rscale);
+         (void) bc_modulo (temp, mod, &temp, scale);
+       }
+
+      bc_multiply (power, power, &power, rscale);
+      (void) bc_modulo (power, mod, &power, scale);
+    }
+
+  /* Assign the value. */
+  bc_free_num (&power);
+  bc_free_num (&exponent);
+  bc_free_num (result);
+  *result = temp;
+  return 0;    /* Everything is OK. */
+}
+
+/* Raise NUM1 to the NUM2 power.  The result is placed in RESULT.
+   Maximum exponent is LONG_MAX.  If a NUM2 is not an integer,
+   only the integer part is used.  */
+
+void
+bc_raise (num1, num2, result, scale)
+     bc_num num1, num2, *result;
+     int scale;
+{
+   bc_num temp, power;
+   long exponent;
+   int rscale;
+   int pwrscale;
+   int calcscale;
+   char neg;
+
+   /* Check the exponent for scale digits and convert to a long. */
+   if (num2->n_scale != 0)
+     bc_rt_warn ("non-zero scale in exponent");
+   exponent = bc_num2long (num2);
+   if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))
+       bc_rt_error ("exponent too large in raise");
+
+   /* Special case if exponent is a zero. */
+   if (exponent == 0)
+     {
+       bc_free_num (result);
+       *result = bc_copy_num (_one_);
+       return;
+     }
+
+   /* Other initializations. */
+   if (exponent < 0)
+     {
+       neg = TRUE;
+       exponent = -exponent;
+       rscale = scale;
+     }
+   else
+     {
+       neg = FALSE;
+       rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale));
+     }
+
+   /* Set initial value of temp.  */
+   power = bc_copy_num (num1);
+   pwrscale = num1->n_scale;
+   while ((exponent & 1) == 0)
+     {
+       pwrscale = 2*pwrscale;
+       bc_multiply (power, power, &power, pwrscale);
+       exponent = exponent >> 1;
+     }
+   temp = bc_copy_num (power);
+   calcscale = pwrscale;
+   exponent = exponent >> 1;
+
+   /* Do the calculation. */
+   while (exponent > 0)
+     {
+       pwrscale = 2*pwrscale;
+       bc_multiply (power, power, &power, pwrscale);
+       if ((exponent & 1) == 1) {
+        calcscale = pwrscale + calcscale;
+        bc_multiply (temp, power, &temp, calcscale);
+       }
+       exponent = exponent >> 1;
+     }
+
+   /* Assign the value. */
+   if (neg)
+     {
+       bc_divide (_one_, temp, result, rscale);
+       bc_free_num (&temp);
+     }
+   else
+     {
+       bc_free_num (result);
+       *result = temp;
+       if ((*result)->n_scale > rscale)
+        (*result)->n_scale = rscale;
+     }
+   bc_free_num (&power);
+}
+
+/* Take the square root NUM and return it in NUM with SCALE digits
+   after the decimal place. */
+
+int
+bc_sqrt (num, scale)
+     bc_num *num;
+     int scale;
+{
+  int rscale, cmp_res, done;
+  int cscale;
+  bc_num guess, guess1, point5, diff;
+
+  /* Initial checks. */
+  cmp_res = bc_compare (*num, _zero_);
+  if (cmp_res < 0)
+    return 0;          /* error */
+  else
+    {
+      if (cmp_res == 0)
+       {
+         bc_free_num (num);
+         *num = bc_copy_num (_zero_);
+         return 1;
+       }
+    }
+  cmp_res = bc_compare (*num, _one_);
+  if (cmp_res == 0)
+    {
+      bc_free_num (num);
+      *num = bc_copy_num (_one_);
+      return 1;
+    }
+
+  /* Initialize the variables. */
+  rscale = MAX (scale, (*num)->n_scale);
+  bc_init_num(&guess);
+  bc_init_num(&guess1);
+  bc_init_num(&diff);
+  point5 = bc_new_num (1,1);
+  point5->n_value[1] = 5;
+
+
+  /* Calculate the initial guess. */
+  if (cmp_res < 0)
+    {
+      /* The number is between 0 and 1.  Guess should start at 1. */
+      guess = bc_copy_num (_one_);
+      cscale = (*num)->n_scale;
+    }
+  else
+    {
+      /* The number is greater than 1.  Guess should start at 10^(exp/2). */
+      bc_int2num (&guess,10);
+
+      bc_int2num (&guess1,(*num)->n_len);
+      bc_multiply (guess1, point5, &guess1, 0);
+      guess1->n_scale = 0;
+      bc_raise (guess, guess1, &guess, 0);
+      bc_free_num (&guess1);
+      cscale = 3;
+    }
+
+  /* Find the square root using Newton's algorithm. */
+  done = FALSE;
+  while (!done)
+    {
+      bc_free_num (&guess1);
+      guess1 = bc_copy_num (guess);
+      bc_divide (*num, guess, &guess, cscale);
+      bc_add (guess, guess1, &guess, 0);
+      bc_multiply (guess, point5, &guess, cscale);
+      bc_sub (guess, guess1, &diff, cscale+1);
+      if (bc_is_near_zero (diff, cscale))
+       {
+         if (cscale < rscale+1)
+           cscale = MIN (cscale*3, rscale+1);
+         else
+           done = TRUE;
+       }
+    }
+
+  /* Assign the number and clean up. */
+  bc_free_num (num);
+  bc_divide (guess,_one_,num,rscale);
+  bc_free_num (&guess);
+  bc_free_num (&guess1);
+  bc_free_num (&point5);
+  bc_free_num (&diff);
+  return 1;
+}
+
+
+/* The following routines provide output for bcd numbers package
+   using the rules of POSIX bc for output. */
+
+/* This structure is used for saving digits in the conversion process. */
+typedef struct stk_rec {
+       long  digit;
+       struct stk_rec *next;
+} stk_rec;
+
+/* The reference string for digits. */
+static char ref_str[] = "0123456789ABCDEF";
+
+
+/* A special output routine for "multi-character digits."  Exactly
+   SIZE characters must be output for the value VAL.  If SPACE is
+   non-zero, we must output one space before the number.  OUT_CHAR
+   is the actual routine for writing the characters. */
+
+void
+bc_out_long (val, size, space, out_char)
+     long val;
+     int size, space;
+#ifdef __STDC__
+     void (*out_char)(int);
+#else
+     void (*out_char)();
+#endif
+{
+  char digits[40];
+  int len, ix;
+
+  if (space) (*out_char) (' ');
+  sprintf (digits, "%ld", val);
+  len = strlen (digits);
+  while (size > len)
+    {
+      (*out_char) ('0');
+      size--;
+    }
+  for (ix=0; ix < len; ix++)
+    (*out_char) (digits[ix]);
+}
+
+/* Output of a bcd number.  NUM is written in base O_BASE using OUT_CHAR
+   as the routine to do the actual output of the characters. */
+
+void
+bc_out_num (num, o_base, out_char, leading_zero)
+     bc_num num;
+     int o_base;
+#ifdef __STDC__
+     void (*out_char)(int);
+#else
+     void (*out_char)();
+#endif
+     int leading_zero;
+{
+  char *nptr;
+  int  index, fdigit, pre_space;
+  stk_rec *digits, *temp;
+  bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;
+
+  /* The negative sign if needed. */
+  if (num->n_sign == MINUS) (*out_char) ('-');
+
+  /* Output the number. */
+  if (bc_is_zero (num))
+    (*out_char) ('0');
+  else
+    if (o_base == 10)
+      {
+       /* The number is in base 10, do it the fast way. */
+       nptr = num->n_value;
+       if (num->n_len > 1 || *nptr != 0)
+         for (index=num->n_len; index>0; index--)
+           (*out_char) (BCD_CHAR(*nptr++));
+       else
+         nptr++;
+
+       if (leading_zero && bc_is_zero (num))
+         (*out_char) ('0');
+
+       /* Now the fraction. */
+       if (num->n_scale > 0)
+         {
+           (*out_char) ('.');
+           for (index=0; index<num->n_scale; index++)
+             (*out_char) (BCD_CHAR(*nptr++));
+         }
+      }
+    else
+      {
+       /* special case ... */
+       if (leading_zero && bc_is_zero (num))
+         (*out_char) ('0');
+
+       /* The number is some other base. */
+       digits = NULL;
+       bc_init_num (&int_part);
+       bc_divide (num, _one_, &int_part, 0);
+       bc_init_num (&frac_part);
+       bc_init_num (&cur_dig);
+       bc_init_num (&base);
+       bc_sub (num, int_part, &frac_part, 0);
+       /* Make the INT_PART and FRAC_PART positive. */
+       int_part->n_sign = PLUS;
+       frac_part->n_sign = PLUS;
+       bc_int2num (&base, o_base);
+       bc_init_num (&max_o_digit);
+       bc_int2num (&max_o_digit, o_base-1);
+
+
+       /* Get the digits of the integer part and push them on a stack. */
+       while (!bc_is_zero (int_part))
+         {
+           bc_modulo (int_part, base, &cur_dig, 0);
+           temp = (stk_rec *) malloc (sizeof(stk_rec));
+           if (temp == NULL) bc_out_of_memory();
+           temp->digit = bc_num2long (cur_dig);
+           temp->next = digits;
+           digits = temp;
+           bc_divide (int_part, base, &int_part, 0);
+         }
+
+       /* Print the digits on the stack. */
+       if (digits != NULL)
+         {
+           /* Output the digits. */
+           while (digits != NULL)
+             {
+               temp = digits;
+               digits = digits->next;
+               if (o_base <= 16)
+                 (*out_char) (ref_str[ (int) temp->digit]);
+               else
+                 bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char);
+               free (temp);
+             }
+         }
+
+       /* Get and print the digits of the fraction part. */
+       if (num->n_scale > 0)
+         {
+           (*out_char) ('.');
+           pre_space = 0;
+           t_num = bc_copy_num (_one_);
+           while (t_num->n_len <= num->n_scale) {
+             bc_multiply (frac_part, base, &frac_part, num->n_scale);
+             fdigit = bc_num2long (frac_part);
+             bc_int2num (&int_part, fdigit);
+             bc_sub (frac_part, int_part, &frac_part, 0);
+             if (o_base <= 16)
+               (*out_char) (ref_str[fdigit]);
+             else {
+               bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
+               pre_space = 1;
+             }
+             bc_multiply (t_num, base, &t_num, 0);
+           }
+           bc_free_num (&t_num);
+         }
+
+       /* Clean up. */
+       bc_free_num (&int_part);
+       bc_free_num (&frac_part);
+       bc_free_num (&base);
+       bc_free_num (&cur_dig);
+       bc_free_num (&max_o_digit);
+      }
+}
+/* Convert a number NUM to a long.  The function returns only the integer
+   part of the number.  For numbers that are too large to represent as
+   a long, this function returns a zero.  This can be detected by checking
+   the NUM for zero after having a zero returned. */
+
+long
+bc_num2long (num)
+     bc_num num;
+{
+  long val;
+  char *nptr;
+  int  index;
+
+  /* Extract the int value, ignore the fraction. */
+  val = 0;
+  nptr = num->n_value;
+  for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--)
+    val = val*BASE + *nptr++;
+
+  /* Check for overflow.  If overflow, return zero. */
+  if (index>0) val = 0;
+  if (val < 0) val = 0;
+
+  /* Return the value. */
+  if (num->n_sign == PLUS)
+    return (val);
+  else
+    return (-val);
+}
+
+
+/* Convert an integer VAL to a bc number NUM. */
+
+void
+bc_int2num (num, val)
+     bc_num *num;
+     int val;
+{
+  char buffer[30];
+  char *bptr, *vptr;
+  int  ix = 1;
+  char neg = 0;
+
+  /* Sign. */
+  if (val < 0)
+    {
+      neg = 1;
+      val = -val;
+    }
+
+  /* Get things going. */
+  bptr = buffer;
+  *bptr++ = val % BASE;
+  val = val / BASE;
+
+  /* Extract remaining digits. */
+  while (val != 0)
+    {
+      *bptr++ = val % BASE;
+      val = val / BASE;
+      ix++;            /* Count the digits. */
+    }
+
+  /* Make the number. */
+  bc_free_num (num);
+  *num = bc_new_num (ix, 0);
+  if (neg) (*num)->n_sign = MINUS;
+
+  /* Assign the digits. */
+  vptr = (*num)->n_value;
+  while (ix-- > 0)
+    *vptr++ = *--bptr;
+}
+
+/* Convert a numbers to a string.  Base 10 only.*/
+
+char
+*num2str (num)
+      bc_num num;
+{
+  char *str, *sptr;
+  char *nptr;
+  int  index, signch;
+
+  /* Allocate the string memory. */
+  signch = ( num->n_sign == PLUS ? 0 : 1 );  /* Number of sign chars. */
+  if (num->n_scale > 0)
+    str = (char *) malloc (num->n_len + num->n_scale + 2 + signch);
+  else
+    str = (char *) malloc (num->n_len + 1 + signch);
+  if (str == NULL) bc_out_of_memory();
+
+  /* The negative sign if needed. */
+  sptr = str;
+  if (signch) *sptr++ = '-';
+
+  /* Load the whole number. */
+  nptr = num->n_value;
+  for (index=num->n_len; index>0; index--)
+    *sptr++ = BCD_CHAR(*nptr++);
+
+  /* Now the fraction. */
+  if (num->n_scale > 0)
+    {
+      *sptr++ = '.';
+      for (index=0; index<num->n_scale; index++)
+       *sptr++ = BCD_CHAR(*nptr++);
+    }
+
+  /* Terminate the string and return it! */
+  *sptr = '\0';
+  return (str);
+}
+/* Convert strings to bc numbers.  Base 10 only.*/
+
+void
+bc_str2num (num, str, scale)
+     bc_num *num;
+     char *str;
+     int scale;
+{
+  int digits, strscale;
+  char *ptr, *nptr;
+  char zero_int;
+
+  /* Prepare num. */
+  bc_free_num (num);
+
+  /* Check for valid number and count digits. */
+  ptr = str;
+  digits = 0;
+  strscale = 0;
+  zero_int = FALSE;
+  if ( (*ptr == '+') || (*ptr == '-'))  ptr++;  /* Sign */
+  while (*ptr == '0') ptr++;                   /* Skip leading zeros. */
+  while (isdigit((int)*ptr)) ptr++, digits++;  /* digits */
+  if (*ptr == '.') ptr++;                      /* decimal point */
+  while (isdigit((int)*ptr)) ptr++, strscale++;        /* digits */
+  if ((*ptr != '\0') || (digits+strscale == 0))
+    {
+      *num = bc_copy_num (_zero_);
+      return;
+    }
+
+  /* Adjust numbers and allocate storage and initialize fields. */
+  strscale = MIN(strscale, scale);
+  if (digits == 0)
+    {
+      zero_int = TRUE;
+      digits = 1;
+    }
+  *num = bc_new_num (digits, strscale);
+
+  /* Build the whole number. */
+  ptr = str;
+  if (*ptr == '-')
+    {
+      (*num)->n_sign = MINUS;
+      ptr++;
+    }
+  else
+    {
+      (*num)->n_sign = PLUS;
+      if (*ptr == '+') ptr++;
+    }
+  while (*ptr == '0') ptr++;                   /* Skip leading zeros. */
+  nptr = (*num)->n_value;
+  if (zero_int)
+    {
+      *nptr++ = 0;
+      digits = 0;
+    }
+  for (;digits > 0; digits--)
+    *nptr++ = CH_VAL(*ptr++);
+
+
+  /* Build the fractional part. */
+  if (strscale > 0)
+    {
+      ptr++;  /* skip the decimal point! */
+      for (;strscale > 0; strscale--)
+       *nptr++ = CH_VAL(*ptr++);
+    }
+}
+
+/* pn prints the number NUM in base 10. */
+
+static void
+out_char (int c)
+{
+  putchar(c);
+}
+
+
+void
+pn (num)
+     bc_num num;
+{
+  bc_out_num (num, 10, out_char, 0);
+  out_char ('\n');
+}
+
+
+/* pv prints a character array as if it was a string of bcd digits. */
+void
+pv (name, num, len)
+     char *name;
+     unsigned char *num;
+     int len;
+{
+  int i;
+  printf ("%s=", name);
+  for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));
+  printf ("\n");
+}
diff --git a/lib/testmul.c b/lib/testmul.c
new file mode 100644 (file)
index 0000000..f7044d6
--- /dev/null
@@ -0,0 +1,244 @@
+/* compute the crossover for recursive and simple multiplication */
+
+#include <stdio.h>
+#include <time.h>
+#include "number.h"
+#ifndef VARARGS
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* from number.c ... */
+extern int mul_base_digits;
+/* extern int mul_small_digits; */
+extern bc_num _one_;
+
+/* global variables */
+int test_n = 1000;
+int test_time = 30 * CLOCKS_PER_SEC;  /* 30 seconds */ 
+
+/* Other things for number.c. */
+int std_only;
+
+void
+out_of_memory()
+{
+  fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
+  exit (1);
+}
+
+/* Runtime error will  print a message and stop the machine. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+rt_error (char *mesg, ...)
+#else
+void
+rt_error (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_error (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+  char error_mesg [255];
+
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vsprintf (error_mesg, mesg, args);
+  va_end (args);
+  
+  fprintf (stderr, "Runtime error: %s\n", error_mesg);
+}
+
+/* A runtime warning tells of some action taken by the processor that
+   may change the program execution but was not enough of a problem
+   to stop the execution. */
+
+#ifndef VARARGS
+#ifdef __STDC__
+void
+rt_warn (char *mesg, ...)
+#else
+void
+rt_warn (mesg)
+     char *mesg;
+#endif
+#else
+void
+rt_warn (mesg, va_alist)
+     char *mesg;
+#endif
+{
+  va_list args;
+  char error_mesg [255];
+
+#ifndef VARARGS   
+  va_start (args, mesg);
+#else
+  va_start (args);
+#endif
+  vsprintf (error_mesg, mesg, args);
+  va_end (args);
+
+  fprintf (stderr, "Runtime warning: %s\n", error_mesg);
+}
+
+void
+out_char (int ch)
+{
+  putchar (ch);
+}
+
+/* Time stuff !!! */
+
+int
+timeit ( bc_num a, bc_num b, int *n)
+{
+  clock_t first;
+  int i, res;
+  bc_num c;
+
+  bc_init_num (&c);
+  first = clock();
+  *n = 0;
+  do {
+    for (i=0; i<test_n; i++)
+      bc_multiply(a,b,&c,0);
+    *n += test_n;
+     res = (int) (clock() - first);
+  } while (res < test_time);
+  return res;
+}
+
+int debug = 0;  /* Print debugging messages? */
+
+int main (int argc, char **argv)
+{
+  bc_num ten, num, expo, big;
+
+  int min, max, mid;
+
+#if 0
+  int smallsize;
+#endif
+
+  int n1, n2;
+  clock_t t1, t2;
+  float permul1, permul2;
+
+  /* args? */
+  if (argc > 1)
+    if (strcmp (argv[1], "-d") == 0)
+      debug = 1;
+
+  bc_init_numbers();
+  bc_init_num (&ten);
+  bc_init_num (&num);
+  bc_init_num (&expo);
+  bc_init_num (&big);
+  bc_int2num (&ten, 10);
+
+  if (debug)
+    fprintf (stderr, "Timings are for %d multiplies\n"
+                    "Minimum time is %d seconds\n", test_n,
+            test_time/CLOCKS_PER_SEC);
+
+  /* Two of the same size */
+  min = 10;
+  max = 500;
+
+  if (debug)
+    fprintf (stderr, "Testing numbers of the same length.\n");
+
+  while (min < max) {
+    mid = (min+max)/2;
+    if (debug) fprintf (stderr,"Checking %d...\n", mid);
+
+    bc_int2num (&expo, mid);
+    bc_raise (ten, expo, &num, 0);
+    bc_sub (num, _one_, &num, 0);
+
+    mul_base_digits = 2*mid+1;
+    t1 = timeit (num, num, &n1);
+    permul1 = (float)t1/(float)n1;
+
+    mul_base_digits = 2*mid-1;
+    t2 = timeit (num, num, &n2);
+    permul2 = (float)t2/(float)n2;
+
+    if (permul1 < permul2)
+      min = mid+1;
+    else
+      max = mid-1;
+
+    if (debug) {
+      fprintf (stderr, "n1 = %d :: n2 = %d\n", n1, n2);
+      fprintf (stderr, "p1 = %f :: p2 = %f\n", permul1, permul2);
+    }
+  }  
+
+  if (debug)
+    fprintf (stderr, "Base digits crossover at %d digits\n", min);
+  printf ("#define MUL_BASE_DIGITS %d\n", 2*min);
+
+
+#if 0
+  mul_base_digits = min;
+
+  /* Small one times a big one. */
+
+  smallsize = min/2;
+  bc_int2num (&expo, smallsize);
+  bc_raise (ten, expo, &big, 0);
+  bc_sub (num, _one_, &big, 0);
+
+  min = min / 2;
+  max = 500;
+
+  if (debug)
+    fprintf (stderr, "Testing numbers of the different length.\n");
+
+  while (min < max) {
+    mid = (min+max)/2;
+    if (debug) fprintf (stderr, "Checking %d...\n", mid);
+
+    bc_int2num (&expo, mid-smallsize);
+    bc_raise (ten, expo, &num, 0);
+    bc_sub (num, _one_, &num, 0);
+
+    mul_small_digits = mid+1;
+    t1 = timeit (big, num, &n1);
+    permul1 = (float)t1/(float)n1;
+
+    mul_small_digits = mid-1;
+    t2 = timeit (big, num, &n2);
+    permul2 = (float)t2/(float)n2;
+
+    if (permul1 < permul2)
+      min = mid+1;
+    else
+      max = mid-1;
+
+    if (debug) {
+      fprintf (stderr, "n1 = %d :: n2 = %d\n", n1, n2);
+      fprintf (stderr, "p1 = %f :: p2 = %f\n", permul1, permul2);
+    }
+  }  
+  
+  if (debug)
+    fprintf (stderr, "Non equal digits crossover at %d total digits\n", min);
+  printf ("#define MUL_SMALL_DIGITS = %d\n", min);
+
+#endif
+
+  return 0;
+}
diff --git a/lib/vfprintf.c b/lib/vfprintf.c
new file mode 100644 (file)
index 0000000..ad53d0c
--- /dev/null
@@ -0,0 +1,31 @@
+/* vfprintf.c -- this was provided for minix.  It may not
+   work on any other system. */
+
+#include "config.h"
+#ifndef HAVE_VPRINTF
+#ifndef HAVE_DOPRINT
+ #error need vfprintf() or doprint()
+#else
+
+#ifdef HAVE_LIB_H
+#include <lib.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+int vfprintf(file, format, argp)
+FILE *file;
+_CONST char *format;
+va_list argp;
+{
+  _doprintf(file, format, argp);
+  if (testflag(file, PERPRINTF)) fflush(file);
+  return 0;
+}
+
+#endif /* HAVE_DOPRINT */
+#endif /* !HAVE_VFPRINTF */
diff --git a/missing b/missing
new file mode 100755 (executable)
index 0000000..e4b838c
--- /dev/null
+++ b/missing
@@ -0,0 +1,134 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois 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., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+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
+
+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        touch file \`y.tab.c'
+  makeinfo     touch the output file
+  yacc         touch file \`y.tab.c'"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing - GNU libit 0.0"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  It should be needed only if
+         you modified \`acinclude.m4' or \`configure.in'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  It should be needed only if
+         you modified \`configure.in'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  It should be needed only if
+         you modified \`acconfig.h' or \`configure.in'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    touch config.h.in
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  It should be needed only if
+         you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+         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$/touch \1.in/' \
+      | sh
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  It should be needed only if
+         your modified any \`.y' file.  For being effective, your
+         modifications might require the \`Bison' package.  Grab it from
+         any GNU archive site."
+    touch y.tab.c
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  It should be needed only 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
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  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 prerequirements 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
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755 (executable)
index 0000000..cc8783e
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do 
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d in ${1+"$@"} ; do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp" 1>&2
+        mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
+     fi
+
+     if test ! -d "$pathcomp"; then
+       errstatus=$lasterr
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/packaging/bc.changes b/packaging/bc.changes
new file mode 100644 (file)
index 0000000..30ae771
--- /dev/null
@@ -0,0 +1,2 @@
+* Mon Mar 10 2014 Patrick McCarty <patrick.mccarty@linux.intel.com> c5ce1cd
+- Minor cleanups for the spec file.
diff --git a/packaging/bc.manifest b/packaging/bc.manifest
new file mode 100644 (file)
index 0000000..017d22d
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+    <domain name="_"/>
+ </request>
+</manifest>
diff --git a/packaging/bc.spec b/packaging/bc.spec
new file mode 100644 (file)
index 0000000..1149c67
--- /dev/null
@@ -0,0 +1,59 @@
+Name:           bc
+
+BuildRequires:  automake
+BuildRequires:  bison
+BuildRequires:  ed
+BuildRequires:  flex
+BuildRequires:  readline-devel
+
+Url:            ftp://ftp.gnu.org/pub/gnu/bc
+License:        GPL-2.0+
+Group:          Base/Utilities
+Version:        1.06
+Release:        0
+Summary:        GNU Command Line Calculator
+Source:         %{name}-%{version}.tar.bz2
+Source1001:     bc.manifest
+
+%description
+bc is an interpreter that supports numbers of arbitrary precision and
+the interactive execution of statements. The syntax has some
+similarities to the C programming language. A standard math library is
+available through command line options. When used, the math library is
+read in before any other input files. bc then reads in all other files
+from the command line, evaluating their contents. Then bc reads from
+standard input (usually the keyboard).
+
+The dc program is also included. dc is a calculator that supports
+reverse-polish notation and allows unlimited precision arithmetic.
+Macros can also be defined. Normally, dc reads from standard input but
+can also read in files specified on the command line. A calculator with
+reverse-polish notation saves numbers to a stack. Arguments to
+mathematical operations (operands) are "pushed" onto the stack until
+the next operator is read in, which "pops" its arguments off the stack
+and "pushes" its results back onto the stack.
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%build
+%reconfigure --with-readline
+
+rm bc/libmath.h
+sed -i 's|\(^_PR.*readline.*$\)|/* \1 */|' bc/scan.l
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root)
+%doc COPYING
+%{_bindir}/bc
+%{_bindir}/dc
+%{_infodir}/*.info*
+%{_mandir}/man1/*
+
+%changelog
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp