summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2000-11-15 20:19:18 +0000
committer <>2013-04-02 19:12:58 +0000
commit5439ab7459283bf61a0256c3a20df164c780ef6c (patch)
treeb44434fc37619db54e956a868b9d99972357d0d4
downloadbc-tarball-5439ab7459283bf61a0256c3a20df164c780ef6c.tar.gz
Imported from /home/lorry/working-area/delta_bc-tarball/bc-1.06.tar.gz.bc-1.06
-rw-r--r--AUTHORS4
-rw-r--r--COPYING340
-rw-r--r--COPYING.LIB515
-rw-r--r--ChangeLog1043
-rw-r--r--Examples/ckbook.b16
-rw-r--r--Examples/pi.b53
-rw-r--r--Examples/primes.b32
-rw-r--r--Examples/twins.b40
-rw-r--r--FAQ17
-rw-r--r--INSTALL176
-rw-r--r--Makefile.am18
-rw-r--r--Makefile.in368
-rw-r--r--NEWS68
-rw-r--r--README86
-rw-r--r--Test/BUG.bc40
-rw-r--r--Test/array.b14
-rw-r--r--Test/arrayp.b30
-rw-r--r--Test/aryprm.b16
-rw-r--r--Test/atan.b5
-rw-r--r--Test/checklib.b109
-rw-r--r--Test/div.b8
-rw-r--r--Test/exp.b3
-rw-r--r--Test/fact.b12
-rw-r--r--Test/jn.b6
-rw-r--r--Test/ln.b4
-rw-r--r--Test/mul.b13
-rw-r--r--Test/raise.b7
-rw-r--r--Test/signum87
-rw-r--r--Test/sine.b5
-rw-r--r--Test/sqrt.b13
-rw-r--r--Test/sqrt1.b13
-rw-r--r--Test/sqrt2.b10
-rw-r--r--Test/testfn.b47
-rwxr-xr-xTest/timetest16
-rw-r--r--acconfig.h24
-rw-r--r--aclocal.m4136
-rw-r--r--bc/Makefile.am42
-rw-r--r--bc/Makefile.in345
-rw-r--r--bc/bc.c1886
-rw-r--r--bc/bc.h42
-rw-r--r--bc/bc.y654
-rw-r--r--bc/bcdefs.h188
-rw-r--r--bc/const.h98
-rw-r--r--bc/execute.c788
-rwxr-xr-xbc/fix-libmath_h9
-rw-r--r--bc/global.c42
-rw-r--r--bc/global.h154
-rw-r--r--bc/libmath.b287
-rw-r--r--bc/libmath.h40
-rw-r--r--bc/load.c351
-rw-r--r--bc/main.c352
-rw-r--r--bc/proto.h148
-rw-r--r--bc/sbc.y448
-rw-r--r--bc/scan.c2259
-rw-r--r--bc/scan.l374
-rw-r--r--bc/storage.c1067
-rw-r--r--bc/util.c873
-rw-r--r--config.h.in81
-rwxr-xr-xconfigure2656
-rw-r--r--configure.in89
-rw-r--r--dc/Makefile.am14
-rw-r--r--dc/Makefile.in296
-rw-r--r--dc/array.c122
-rw-r--r--dc/dc-proto.h90
-rw-r--r--dc/dc-regdef.h43
-rw-r--r--dc/dc.c183
-rw-r--r--dc/dc.h82
-rw-r--r--dc/eval.c682
-rw-r--r--dc/misc.c179
-rw-r--r--dc/numeric.c600
-rw-r--r--dc/stack.c494
-rw-r--r--dc/string.c211
-rw-r--r--doc/Makefile.am12
-rw-r--r--doc/Makefile.in355
-rw-r--r--doc/bc.1792
-rw-r--r--doc/bc.info999
-rw-r--r--doc/bc.texi1014
-rw-r--r--doc/dc.1488
-rw-r--r--doc/dc.info441
-rw-r--r--doc/dc.texi526
-rw-r--r--doc/texinfo.tex5992
-rw-r--r--h/getopt.h133
-rw-r--r--h/number.h153
-rwxr-xr-xinstall-sh238
-rw-r--r--lib/Makefile.am26
-rw-r--r--lib/Makefile.in283
-rw-r--r--lib/getopt.c752
-rw-r--r--lib/getopt1.c184
-rw-r--r--lib/number.c1793
-rw-r--r--lib/testmul.c244
-rw-r--r--lib/vfprintf.c31
-rwxr-xr-xmissing134
-rwxr-xr-xmkinstalldirs36
-rw-r--r--stamp-h.in1
94 files changed, 34290 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
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
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.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 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
index 0000000..c4792dd
--- /dev/null
+++ b/COPYING.LIB
@@ -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.
+
+ 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
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
index 0000000..5815ea0
--- /dev/null
+++ b/Examples/ckbook.b
@@ -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
index 0000000..0d840cf
--- /dev/null
+++ b/Examples/pi.b
@@ -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
index 0000000..2b52ca7
--- /dev/null
+++ b/Examples/primes.b
@@ -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
index 0000000..de910a7
--- /dev/null
+++ b/Examples/twins.b
@@ -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
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
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
index 0000000..6703d74
--- /dev/null
+++ b/Makefile.am
@@ -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
index 0000000..b57eae5
--- /dev/null
+++ b/Makefile.in
@@ -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
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
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
index 0000000..254eefe
--- /dev/null
+++ b/Test/BUG.bc
@@ -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
index 0000000..a0341ec
--- /dev/null
+++ b/Test/array.b
@@ -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
index 0000000..3f3ca50
--- /dev/null
+++ b/Test/arrayp.b
@@ -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
index 0000000..9d3f95b
--- /dev/null
+++ b/Test/aryprm.b
@@ -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
index 0000000..e742279
--- /dev/null
+++ b/Test/atan.b
@@ -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
index 0000000..44c1fac
--- /dev/null
+++ b/Test/checklib.b
@@ -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
index 0000000..3c7d377
--- /dev/null
+++ b/Test/div.b
@@ -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
index 0000000..92c482c
--- /dev/null
+++ b/Test/exp.b
@@ -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
index 0000000..995a26d
--- /dev/null
+++ b/Test/fact.b
@@ -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
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
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
index 0000000..722086f
--- /dev/null
+++ b/Test/mul.b
@@ -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
index 0000000..ec6929d
--- /dev/null
+++ b/Test/raise.b
@@ -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
index 0000000..9e27d2d
--- /dev/null
+++ b/Test/signum
@@ -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
index 0000000..18c4b57
--- /dev/null
+++ b/Test/sine.b
@@ -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
index 0000000..3fb548c
--- /dev/null
+++ b/Test/sqrt.b
@@ -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
index 0000000..c3ca269
--- /dev/null
+++ b/Test/sqrt1.b
@@ -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
index 0000000..bd0eaad
--- /dev/null
+++ b/Test/sqrt2.b
@@ -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
index 0000000..7578fc5
--- /dev/null
+++ b/Test/testfn.b
@@ -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
index 0000000..1a4d0ea
--- /dev/null
+++ b/Test/timetest
@@ -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
index 0000000..ff17f82
--- /dev/null
+++ b/acconfig.h
@@ -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
index 0000000..102dc3e
--- /dev/null
+++ b/aclocal.m4
@@ -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
index 0000000..9187339
--- /dev/null
+++ b/bc/Makefile.am
@@ -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
index 0000000..18ebce0
--- /dev/null
+++ b/bc/Makefile.in
@@ -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
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
+
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (to, from, count)
+ char *to;
+ char *from;
+ unsigned int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+ register char *t = to;
+ register char *f = from;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 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"
+
+ 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
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
index 0000000..403e326
--- /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 >= 0)
+ generate ("p");
+ $4 = next_label++;
+ sprintf (genstr, "N%1d:", $4);
+ generate (genstr);
+ }
+ opt_expression ';'
+ {
+ if ($7 < 0) 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
index 0000000..260cd12
--- /dev/null
+++ b/bc/bcdefs.h
@@ -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
index 0000000..1a7c5b8
--- /dev/null
+++ b/bc/const.h
@@ -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
index 0000000..d2864d1
--- /dev/null
+++ b/bc/execute.c
@@ -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
index 0000000..f973a8c
--- /dev/null
+++ b/bc/fix-libmath_h
@@ -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
index 0000000..5d1205c
--- /dev/null
+++ b/bc/global.c
@@ -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
index 0000000..cf6945c
--- /dev/null
+++ b/bc/global.h
@@ -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
index 0000000..7bb6405
--- /dev/null
+++ b/bc/libmath.b
@@ -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
index 0000000..bf48f4b
--- /dev/null
+++ b/bc/libmath.h
@@ -0,0 +1,40 @@
+{"@iK20:s2:p@r",
+"@iF1,5.6,7,8,9,10,11,12,13,14[l5:0<Z1:1s11:pl5:ns5:pN1:l2:s14:",
+"pK6:l14:+K.44:l5:*+s12:pl5:cS1+s2:pN2:l5:1>Z3:l9:1+s9:pl5:K2:",
+"/s5:pl2:1+s2:pJ2:N3:l12:s2:p1l5:+s13:pl5:s6:p1s7:pK2:s10:pN5:",
+"1B6:J4:N7:l10:i10:pJ5:N6:l6:l5:*s6:l7:l10:*s7:/s8:pl8:0=Z8:l9:",
+"0>Z9:N10:l9:d9:Z11:l13:l13:*s13:pJ10:N11:N9:l14:s2:pl11:Z12:1",
+"l13:/RN12:l13:1/RN8:l13:l8:+s13:pJ7:N4:0R]@r",
+"@iF2,5.8,9,10,11,12,13,14[l5:0{Z1:1K10:l2:^-1/RN1:l2:s14:pK6:",
+"l2:+s2:pK2:s9:p0s10:pN2:l5:K2:}Z3:l9:K2:*s9:pl5:cRs5:pJ2:N3:N4:",
+"l5:K.5:{Z5:l9:K2:*s9:pl5:cRs5:pJ4:N5:l5:1-l5:1+/s12:s13:pl12:",
+"l12:*s11:pK3:s10:pN7:1B8:J6:N9:l10:K2:+s10:pJ7:N8:l12:l11:*s12:",
+"l10:/s8:pl8:0=Z10:l9:l13:*s13:pl14:s2:pl13:1/RN10:l13:l8:+s13:",
+"pJ9:N6:0R]@r",
+"@iF3,5.8,10,11,12,15,13,14[l2:s14:pK1.1:l14:*K2:+s2:p1C4,0:s13:",
+"pl5:0<Z1:1s11:pl5:ns5:pN1:0s2:pl5:l13:/K2:+K4:/s12:pl5:K4:l12:",
+"*l13:*-s5:pl12:K2:%Z2:l5:ns5:pN2:l14:K2:+s2:pl5:s8:s13:pl5:nl5:",
+"*s15:pK3:s10:pN4:1B5:J3:N6:l10:K2:+s10:pJ4:N5:l8:l15:l10:l10:",
+"1-*/*s8:pl8:0=Z7:l14:s2:pl11:Z8:l13:n1/RN8:l13:1/RN7:l13:l8:+",
+"s13:pJ6:N3:0R]@r",
+"@iF5,5.13,14[l2:s14:pl2:K1.2:*s2:pl5:1C4,0:K2:*+C3,0:s13:pl14:",
+"s2:pl13:1/R0R]@r",
+"@iF4,5.6,8,9,10,11,12,15,13,14[1s11:pl5:0<Z1:1ns11:pl5:ns5:pN1:",
+"l5:1=Z2:l2:K25:{Z3:K.7853981633974483096156608:l11:/RN3:l2:K40",
+":{Z4:K.7853981633974483096156608458198757210492:l11:/RN4:l2:K",
+"60:{Z5:K.785398163397448309615660845819875721049292349843776455243736",
+":l11:/RN5:N2:l5:K.2:=Z6:l2:K25:{Z7:K.1973955598498807583700497",
+":l11:/RN7:l2:K40:{Z8:K.1973955598498807583700497651947902934475",
+":l11:/RN8:l2:K60:{Z9:K.197395559849880758370049765194790293447585103787852101517688",
+":l11:/RN9:N6:l2:s14:pl5:K.2:>Z10:l14:K5:+s2:pK.2:C4,0:s6:pN10:",
+"l14:K3:+s2:pN11:l5:K.2:>Z12:l9:1+s9:pl5:K.2:-1l5:K.2:*+/s5:pJ11:N12:",
+"l5:s12:s13:pl5:nl5:*s15:pK3:s10:pN14:1B15:J13:N16:l10:K2:+s10:",
+"pJ14:N15:l12:l15:*s12:l10:/s8:pl8:0=Z17:l14:s2:pl9:l6:*l13:+l11:",
+"/RN17:l13:l8:+s13:pJ16:N13:0R]@r",
+"@iF6,12,5.6,16,7,8,9,10,11,15,13,14[l2:s14:p0s2:pl12:1/s12:pl12:",
+"0<Z1:l12:ns12:pl12:K2:%1=Z2:1s11:pN2:N1:l0:s16:pKA:s0:p1s9:pK",
+"2:s10:pN4:l10:l12:{B5:J3:N6:l10:i10:pJ4:N5:l9:l10:*s9:pJ6:N3:",
+"K1.5:l14:*s2:pl5:l12:^K2:l12:^/l9:/s9:p1s8:s13:pl5:nl5:*K4:/s15:",
+"pK1.5:l14:*l9:cL+l9:cS-s2:p1s10:pN8:1B9:J7:N10:l10:i10:pJ8:N9:",
+"l8:l15:*l10:/l12:l10:+/s8:pl8:0=Z11:l16:s0:pl14:s2:pl11:Z12:l9:",
+"nl13:*1/RN12:l9:l13:*1/RN11:l13:l8:+s13:pJ10:N7:0R]@r",0}
diff --git a/bc/load.c b/bc/load.c
new file mode 100644
index 0000000..40b8051
--- /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;
+
+ /* 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
index 0000000..1b9f6d2
--- /dev/null
+++ b/bc/main.c
@@ -0,0 +1,352 @@
+/* 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 '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
index 0000000..1e7311f
--- /dev/null
+++ b/bc/proto.h
@@ -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
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
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
index 0000000..b4addaa
--- /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
index 0000000..10ebf5c
--- /dev/null
+++ b/bc/storage.c
@@ -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
index 0000000..c305c2e
--- /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 (FALSE);
+ 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 (FALSE);
+ 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
index 0000000..ebb9e34
--- /dev/null
+++ b/config.h.in
@@ -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
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
index 0000000..5f982d3
--- /dev/null
+++ b/configure.in
@@ -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 -I8"
+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
index 0000000..99164ba
--- /dev/null
+++ b/dc/Makefile.am
@@ -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
index 0000000..0772dd6
--- /dev/null
+++ b/dc/Makefile.in
@@ -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
index 0000000..d97f716
--- /dev/null
+++ b/dc/array.c
@@ -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
index 0000000..f0ac28b
--- /dev/null
+++ b/dc/dc-proto.h
@@ -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
index 0000000..540268c
--- /dev/null
+++ b/dc/dc-regdef.h
@@ -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
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);
+}
+
+
+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
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
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;
+
+
+/* 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++;
+}
+
+
+
+/* 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;
+}
+
+
+/* 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;
+}
+
+
+/* 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;
+}
+
+
+/* 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
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
+
+
+/* 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;
+}
+
+
+/* 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);
+}
+
+
+/* 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();
+}
+
+
+/* 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);
+}
+
+
+/* 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
index 0000000..6086be5
--- /dev/null
+++ b/dc/numeric.c
@@ -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));
+}
+
+/* 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((bc_num *)&result.v.number);
+ bc_int2num((bc_num *)&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;
+}
+
+
+/* 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;
+}
+
+
+/* initialize the math subsystem */
+void
+dc_math_init DC_DECLVOID()
+{
+ bc_init_numbers();
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+
+
+/*---------------------------------------------------------------------------\
+| 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
index 0000000..1d8a9bf
--- /dev/null
+++ b/dc/stack.c
@@ -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];
+
+
+/* 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;
+}
+
+
+/* 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);
+ }
+}
+
+
+/* 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;
+}
+
+
+/* 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;
+}
+
+
+
+/* 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);
+}
+
+
+
+
+/* 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
index 0000000..a7f79a4
--- /dev/null
+++ b/dc/string.c
@@ -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 */
+};
+
+
+/* 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;
+}
+
+
+/* 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
index 0000000..a729cee
--- /dev/null
+++ b/doc/Makefile.am
@@ -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
index 0000000..840d007
--- /dev/null
+++ b/doc/Makefile.in
@@ -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
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
index 0000000..2aa2685
--- /dev/null
+++ b/doc/bc.info
@@ -0,0 +1,999 @@
+This is bc.info, produced by makeinfo version 4.0 from bc.texi.
+
+
+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::
+
+
+File: bc.info, Node: Introduction, Next: Basic Elements, Prev: Top, Up: Top
+
+Introduction
+************
+
+* Menu:
+
+* Description::
+* Command Line Options::
+
+
+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.
+
+
+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.
+
+
+File: bc.info, Node: Basic Elements, Next: Expressions, Prev: Introduction, Up: Top
+
+Basic Elements
+**************
+
+* Menu:
+
+* Numbers::
+* Variables::
+* Comments::
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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::
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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); }
+
+
+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.
+
+
+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);
+ }
+
+
+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.
+
+
+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'.
+
+
+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.
+
+
+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.
+
+
+
+Tag Table:
+Node: Top65
+Node: Introduction354
+Node: Description515
+Node: Command Line Options1969
+Node: Basic Elements2533
+Node: Numbers2704
+Node: Variables3467
+Node: Comments4576
+Node: Expressions5317
+Node: About Expressions and Special Variables5597
+Node: Basic Expressions7333
+Node: Relational Expressions10274
+Node: Boolean Expressions11279
+Node: Precedence11834
+Node: Special Expressions12994
+Node: Statements14376
+Node: Pseudo Statements21001
+Node: Functions21649
+Node: Math Library Functions25703
+Node: Examples26413
+Node: Readline and Libedit Options28431
+Node: GNU `bc' and Other Implementations29458
+Node: Limits34700
+Node: Environment Variables35953
+
+End Tag Table
diff --git a/doc/bc.texi b/doc/bc.texi
new file mode 100644
index 0000000..a7cb9f6
--- /dev/null
+++ b/doc/bc.texi
@@ -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
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
index 0000000..050a6b3
--- /dev/null
+++ b/doc/dc.info
@@ -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.
+
+
+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
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.)
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+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.
+
+
+File: dc.info, Node: Reporting bugs, Prev: Miscellaneous, Up: Top
+
+Reporting bugs
+**************
+
+ Email bug reports to <bug-dc@gnu.org>.
+
+
+
+Tag Table:
+Node: Top1084
+Node: Introduction1663
+Node: Invocation2880
+Node: Printing Commands3724
+Node: Arithmetic4902
+Node: Stack Control7815
+Node: Registers8228
+Node: Parameters9154
+Node: Strings10415
+Node: Status Inquiry13385
+Node: Miscellaneous13942
+Node: Reporting bugs14909
+
+End Tag Table
diff --git a/doc/dc.texi b/doc/dc.texi
new file mode 100644
index 0000000..0a4d973
--- /dev/null
+++ b/doc/dc.texi
@@ -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
index 0000000..c49af9f
--- /dev/null
+++ b/doc/texinfo.tex
@@ -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
index 0000000..f3696d9
--- /dev/null
+++ b/h/getopt.h
@@ -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
index 0000000..8d78120
--- /dev/null
+++ b/h/number.h
@@ -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
index 0000000..ab74c88
--- /dev/null
+++ b/install-sh
@@ -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
index 0000000..6f74b4d
--- /dev/null
+++ b/lib/Makefile.am
@@ -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
index 0000000..5ffa593
--- /dev/null
+++ b/lib/Makefile.in
@@ -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
index 0000000..23ce064
--- /dev/null
+++ b/lib/getopt.c
@@ -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. */
+
+/* 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;
+
+#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__ */
+
+/* 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;
+}
+
+/* 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__. */
+
+#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
index 0000000..de8e2ad
--- /dev/null
+++ b/lib/getopt1.c
@@ -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. */
+
+#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__. */
+
+#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
index 0000000..1f913d5
--- /dev/null
+++ b/lib/number.c
@@ -0,0 +1,1793 @@
+/* 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. */
+
+#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
index 0000000..f7044d6
--- /dev/null
+++ b/lib/testmul.c
@@ -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
index 0000000..ad53d0c
--- /dev/null
+++ b/lib/vfprintf.c
@@ -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
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
index 0000000..cc8783e
--- /dev/null
+++ b/mkinstalldirs
@@ -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/stamp-h.in b/stamp-h.in
new file mode 100644
index 0000000..9788f70
--- /dev/null
+++ b/stamp-h.in
@@ -0,0 +1 @@
+timestamp