diff options
Diffstat (limited to 'contrib/bc')
94 files changed, 23353 insertions, 0 deletions
diff --git a/contrib/bc/AUTHORS b/contrib/bc/AUTHORS new file mode 100644 index 0000000..b665a63 --- /dev/null +++ b/contrib/bc/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/contrib/bc/COPYING b/contrib/bc/COPYING new file mode 100644 index 0000000..86cf81a --- /dev/null +++ b/contrib/bc/COPYING @@ -0,0 +1,341 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/contrib/bc/ChangeLog b/contrib/bc/ChangeLog new file mode 100644 index 0000000..f277079 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Examples/ckbook.b b/contrib/bc/Examples/ckbook.b new file mode 100644 index 0000000..5815ea0 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Examples/pi.b b/contrib/bc/Examples/pi.b new file mode 100644 index 0000000..0d840cf --- /dev/null +++ b/contrib/bc/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/contrib/bc/Examples/primes.b b/contrib/bc/Examples/primes.b new file mode 100644 index 0000000..2b52ca7 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Examples/twins.b b/contrib/bc/Examples/twins.b new file mode 100644 index 0000000..de910a7 --- /dev/null +++ b/contrib/bc/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/contrib/bc/FAQ b/contrib/bc/FAQ new file mode 100644 index 0000000..32dd051 --- /dev/null +++ b/contrib/bc/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/contrib/bc/FREEBSD-upgrade b/contrib/bc/FREEBSD-upgrade new file mode 100644 index 0000000..6552a9c --- /dev/null +++ b/contrib/bc/FREEBSD-upgrade @@ -0,0 +1,13 @@ +$FreeBSD$ + +bc 1.0.5a + originals can be found at: ftp://prep.ai.mit.edu/pub/gnu/ + removed no subdirectories + removed bc/scan.c bc/bc.c bc/bc.h doc/texinfo.tex doc/dc.info + obrien@FreeBSD.ORG + + Imported with the commands: + + tar xvzf bc-1.0.5a.tar.gz + cd bc-1.0.5 + cvs import src/contrib/bc BC bc_1_0_5a diff --git a/contrib/bc/INSTALL b/contrib/bc/INSTALL new file mode 100644 index 0000000..3b50ea9 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Makefile.am b/contrib/bc/Makefile.am new file mode 100644 index 0000000..6703d74 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Makefile.in b/contrib/bc/Makefile.in new file mode 100644 index 0000000..b57eae5 --- /dev/null +++ b/contrib/bc/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/contrib/bc/NEWS b/contrib/bc/NEWS new file mode 100644 index 0000000..fc02a0d --- /dev/null +++ b/contrib/bc/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/contrib/bc/README b/contrib/bc/README new file mode 100644 index 0000000..2813fb8 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/BUG.bc b/contrib/bc/Test/BUG.bc new file mode 100644 index 0000000..254eefe --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/TESTS.bc b/contrib/bc/Test/TESTS.bc new file mode 100644 index 0000000..ec42172 --- /dev/null +++ b/contrib/bc/Test/TESTS.bc @@ -0,0 +1,565 @@ +From phil@cs.wwu.edu Mon Mar 20 23:13:22 1995 +Date: Mon, 20 Mar 1995 23:12:17 -0800 +From: Phil Nelson <phil@cs.wwu.edu> +To: phil@steelhead.cs.wwu.edu +Subject: [jhn@ironwood.cray.com: XPG4 bc(1) failures] + +From: jhn@ironwood.cray.com (James Nordby) +Subject: XPG4 bc(1) failures +To: phil@cs.wwu.edu +Date: Fri, 17 Mar 1995 12:14:13 -0600 (CST) +X-Mailer: ELM [version 2.4 PL24-CRI-b] +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: 7bit +Content-Length: 14277 + + +Phil, + +Here are the test results I'm getting from the XPG4 test suite, +with some explanation and fixes so far. Let me know what you +think... + +Thanks much, +Jim Nordby (jhn@cray.com) + + +-------- bc 08:38:34 -------- + +Assertion #20 (A): bc reads text files +Expected exit code = 0; Received 139 +Standard output isn't the same as file 'bc_eso_20_1' +diff of "out.stdout" and "bc_eso_20_1": +*** out.stdout Fri Mar 17 08:39:22 1995 +--- bc_eso_20_1 Fri Mar 17 08:39:22 1995 +*************** +*** 0 **** +--- 1,31 ---- ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 11111111111111111111111111111111111111111111111111111111111111111111 ++ 1111111 +Assertion Result: FAIL + +I couldn't reproduce this problem; when I rebuilt your bc and +ran it, I got a different problem with printing out a large +number. The XPG4 tests expected lines to be 70 characters +long, INCLUDING the newline (this comes from the POSIX definition +of a line). To fix it, I changed util.c like so: + +*** util.c Thu Mar 16 10:47:36 1995 +--- util.c.old Thu Mar 16 10:50:10 1995 +*************** +*** 309,323 **** + else + { + out_col++; +- #ifdef _CRAY +- /* +- * XPG4 considers a line to include the <newline>; +- * therefore we want 68 numerals, <backslash>, <newline> +- */ +- if (out_col == 69) +- #else + if (out_col == 70) +- #endif + { + putchar ('\\'); + putchar ('\n'); +--- 309,315 ---- + + + + + + +Assertion #42 (A): check reserved words +Standard error isn't empty +Contents of out.stderr: +(standard_in) 6: syntax error +(standard_in) 15: syntax error +Standard output isn't the same as file 'bc_eso_42_1' +diff of "out.stdout" and "bc_eso_42_1": +*** out.stdout Fri Mar 17 08:39:43 1995 +--- bc_eso_42_1 Fri Mar 17 08:39:43 1995 +*************** +*** 1,2 **** +--- 1,3 ---- + 2 + 1 ++ 0 +Assertion Result: FAIL + +This one is debatable, based on the grammar in the POSIX manual. +Here's the input file: + +cat << \VSC-EOF > input +define a() { + auto b; + for ( b = 0; b < 10; b++ ) { + b; + if ( b == 1 ) + break; + } + return ( 5 ) ; +} +ibase = 10; +length ( obase ); +scale = 0; +sqrt(1); +while ( a() != 5 ) +VSC-EOF + +They want these constructs to be accepted: + + +if (b == 1) + whatever; +for (x = 0; x < 10; x++) + whatever; +while (x < 10) + whatever; + +rather than just + +if (b == 1) { + whatever +} +etc. + +The grammar as it's currently worded requires a '{' before hitting +a NEWLINE for these constructs. It's easy enough to change in bc.y +(see below), but if I do change it, it still barfs on the last +line of the file ( 'while (a() != 5)' ). Since the while lacks +a body, it gives a syntax error; they're expecting a '0' to be +returned. The grammar could be changed to support this, but is +it a good idea? + + +*** bc.y Thu Mar 16 10:47:20 1995 +--- bc.y.old Thu Mar 16 10:50:11 1995 +*************** +*** 142,150 **** + | error statement + { $$ = $2; } + ; +- allow_newlines : /* empty */ +- | NEWLINE allow_newlines +- ; + statement : Warranty + { warranty (""); } + | Limits +--- 142,147 ---- +*************** +*** 231,237 **** + sprintf (genstr, "pJ%1d:N%1d:", $4, $7); + generate (genstr); + } +! allow_newlines statement + { + sprintf (genstr, "J%1d:N%1d:", + continue_label, break_label); +--- 228,234 ---- + sprintf (genstr, "pJ%1d:N%1d:", $4, $7); + generate (genstr); + } +! statement + { + sprintf (genstr, "J%1d:N%1d:", + continue_label, break_label); +*************** +*** 246,252 **** + sprintf (genstr, "Z%1d:", if_label); + generate (genstr); + } +! allow_newlines statement opt_else + { + sprintf (genstr, "N%1d:", if_label); + generate (genstr); +--- 243,249 ---- + sprintf (genstr, "Z%1d:", if_label); + generate (genstr); + } +! statement opt_else + { + sprintf (genstr, "N%1d:", if_label); + generate (genstr); +*************** +*** 265,271 **** + sprintf (genstr, "Z%1d:", break_label); + generate (genstr); + } +! ')' allow_newlines statement + { + sprintf (genstr, "J%1d:N%1d:", $1, break_label); + generate (genstr); +--- 262,268 ---- + sprintf (genstr, "Z%1d:", break_label); + generate (genstr); + } +! ')' statement + { + sprintf (genstr, "J%1d:N%1d:", $1, break_label); + generate (genstr); + + + + +Assertion #49 (A): check strings +Expected exit code = 0; Received 1 +Standard error isn't empty +Contents of out.stderr: +File (NULL) is unavailable. +Standard output isn't the same as file 'bc_eso_49_1' +diff of "out.stdout" and "bc_eso_49_1": +cmd-1794 diff: Missing newline at end of file 'bc_eso_49_1'. +*** out.stdout Fri Mar 17 08:40:01 1995 +--- bc_eso_49_1 Fri Mar 17 08:40:01 1995 +*************** +*** 0 **** +--- 1 ---- ++ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +*LINE CONTINUATION -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +*LINE CONTINUATION -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Assertion Result: FAIL + +This gist of this is that the standard expects numbers to +be truncated to 70 characters, but STRINGS should not. +My changes to fix this are: + + +*** execute.c Thu Mar 16 13:06:39 1995 +--- execute.c.old Thu Mar 16 10:50:09 1995 +*************** +*** 208,218 **** + case 'O' : /* Write a string to the output with processing. */ + while ((ch = byte(&pc)) != '"') + if (ch != '\\') +- #ifdef _CRAY +- putchar (ch); +- #else + out_char (ch); +- #endif + else + { + ch = byte(&pc); +--- 207,213 ---- +*************** +*** 219,234 **** + if (ch == '"') break; + switch (ch) + { +- #ifdef _CRAY +- case 'a': putchar (007); break; +- case 'b': putchar ('\b'); break; +- case 'f': putchar ('\f'); break; +- case 'n': putchar ('\n'); break; +- case 'q': putchar ('"'); break; +- case 'r': putchar ('\r'); break; +- case 't': putchar ('\t'); break; +- case '\\': putchar ('\\'); break; +- #else + case 'a': out_char (007); break; + case 'b': out_char ('\b'); break; + case 'f': out_char ('\f'); break; +--- 214,219 ---- +*************** +*** 237,243 **** + case 'r': out_char ('\r'); break; + case 't': out_char ('\t'); break; + case '\\': out_char ('\\'); break; +- #endif + default: break; + } + } +--- 222,227 ---- +*************** +*** 350,360 **** + break; + + case 'w' : /* Write a string to the output. */ +- #ifdef _CRAY +- while ((ch = byte(&pc)) != '"') putchar (ch); +- #else + while ((ch = byte(&pc)) != '"') out_char (ch); +- #endif + if (interactive) fflush (stdout); + break; + + + + +Assertion #77 (C): output longer than 70 characters +Standard output isn't the same as file 'bc_eso_77_1' +diff of "out.stdout" and "bc_eso_77_1": +*** out.stdout Fri Mar 17 08:41:13 1995 +--- bc_eso_77_1 Fri Mar 17 08:41:13 1995 +*************** +*** 1,2 **** +! 3.3333333333333333333333333333333333333333333333333333333333333333333 +! 33333333333333333333333333333333 +--- 1,2 ---- +! 3.333333333333333333333333333333333333333333333333333333333333333333 +! 333333333333333333333333333333333 +Assertion Result: FAIL + +Same as assertion #20 above... + + + + +Assertion #92 (A): check % +Standard output isn't the same as file 'bc_eso_92_1' +diff of "out.stdout" and "bc_eso_92_1": +*** out.stdout Fri Mar 17 08:41:33 1995 +--- bc_eso_92_1 Fri Mar 17 08:41:33 1995 +*************** +*** 4,8 **** + 4 + 15 + 1 +! 0 +! 0 +--- 4,8 ---- + 4 + 15 + 1 +! 6 +! 5 +Assertion Result: FAIL + +This one is a pain. The failing code looks like this: + +scale = 4 +scale ( 5.000000 % 2.0 ) +scale ( 5.00 % 2.0 ) + +They expect '6' and '5' for output, instead of '0', based on +the explanation of the modulus operator ("scale of the result +shall be 'max(scale + scale(b), scale(a)'"), even though the +result is a 0. I was able to fix this problem by the change +below: + +*** number.c Thu Mar 16 13:15:43 1995 +--- number.c.old Thu Mar 16 10:50:09 1995 +*************** +*** 614,623 **** + case 0: + /* They are equal! return zero! */ + diff = copy_num (_zero_); +- #ifdef _CRAY +- /* correct the scale here */ +- diff->n_scale = MAX (n1->n_scale, n2->n_scale); +- #endif + break; + case 1: + /* n2 is less than n1, subtract n2 from n1. */ + +but this causes another test failure that I haven't looked at. + + + + +Assertion #130 (A): functions are call by value +Standard output isn't the same as file 'bc_eso_130_1' +diff of "out.stdout" and "bc_eso_130_1": +*** out.stdout Fri Mar 17 08:42:24 1995 +--- bc_eso_130_1 Fri Mar 17 08:42:24 1995 +*************** +*** 4,10 **** + 5 + 4 + 0 +! 4 + 3 + 3 + 5 +--- 4,10 ---- + 5 + 4 + 0 +! 5 + 3 + 3 + 5 +Assertion Result: FAIL + +Assertion #131 (A): functions are call by value +Standard output isn't the same as file 'bc_eso_131_1' +diff of "out.stdout" and "bc_eso_131_1": +*** out.stdout Fri Mar 17 08:42:28 1995 +--- bc_eso_131_1 Fri Mar 17 08:42:28 1995 +*************** +*** 4,10 **** + 5 + 4 + 0 +! 4 + 3 + 3 + 5 +--- 4,10 ---- + 5 + 4 + 0 +! 5 + 3 + 3 + 5 +Assertion Result: FAIL + + +Both of these are the 'arrays are passed by value' problem. +One of the test cases is below: + +cat << \VSC-EOF > bc_in_130_1 +a[0] = 3 +a[0] +define b(a[]) { +a[0] +a[0] = 4 +a[0] +} +a[0] +a[0] = 5 +a[0] +b(a[]) +a[0] +VSC-EOF + +They expect the assignment of a[0] inside the b() function +to not affect a[0] outside of the function. + + + + + +Assertion #139 (A): check sin +Standard output isn't the same as file 'bc_eso_139_1' +diff of "out.stdout" and "bc_eso_139_1": +*** out.stdout Fri Mar 17 08:42:40 1995 +--- bc_eso_139_1 Fri Mar 17 08:42:39 1995 +*************** +*** 1,5 **** + 0 +! 20 + 1.68294196961579301330 + 20 + 1.6829419696 +--- 1,5 ---- + 0 +! 0 + 1.68294196961579301330 + 20 + 1.6829419696 +Assertion Result: FAIL + +Assertion #141 (A): check arctanngent +Standard output isn't the same as file 'bc_eso_141_1' +diff of "out.stdout" and "bc_eso_141_1": +*** out.stdout Fri Mar 17 08:42:44 1995 +--- bc_eso_141_1 Fri Mar 17 08:42:44 1995 +*************** +*** 1,5 **** + 0 +! 20 + 3.14159265358979323844 + 20 + 3.1415926532 +--- 1,5 ---- + 0 +! 0 + 3.14159265358979323844 + 20 + 3.1415926532 +Assertion Result: FAIL + +Assertion #142 (A): check log +Standard output isn't the same as file 'bc_eso_142_1' +diff of "out.stdout" and "bc_eso_142_1": +*** out.stdout Fri Mar 17 08:42:47 1995 +--- bc_eso_142_1 Fri Mar 17 08:42:47 1995 +*************** +*** 1,5 **** + 0 +! 20 + 2.30258509299404568401 + 20 + 2.3025850929 +--- 1,5 ---- + 0 +! 0 + 2.30258509299404568401 + 20 + 2.3025850929 +Assertion Result: FAIL + +Assertion #144 (A): check bessel +Standard output isn't the same as file 'bc_eso_144_1' +diff of "out.stdout" and "bc_eso_144_1": +*** out.stdout Fri Mar 17 08:42:51 1995 +--- bc_eso_144_1 Fri Mar 17 08:42:51 1995 +*************** +*** 1,5 **** + 0 +! 20 + .57672480775687338720 + 20 + .5767248077 +--- 1,5 ---- + 0 +! 0 + .57672480775687338720 + 20 + .5767248077 +Assertion Result: FAIL + +All of these are the same. I'll give you the test case +for 'sin'; what they're expecting is 0: + +scale(s(0)) + +bc outputs '20' (which is the scale at the time), but the +interpretation of the standard says that it should be '0', +since s(0) is 0, and the scale of 0 is 0. I think that +this interpretation disagrees with one of the previous +assertions (assertion #92). + +/* end of test results */ + + + +-- +Phil Nelson +e-mail: phil@cs.wwu.edu +http://www.cs.wwu.edu/~phil + + diff --git a/contrib/bc/Test/array.b b/contrib/bc/Test/array.b new file mode 100644 index 0000000..a0341ec --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/arrayp.b b/contrib/bc/Test/arrayp.b new file mode 100644 index 0000000..3f3ca50 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/aryprm.b b/contrib/bc/Test/aryprm.b new file mode 100644 index 0000000..9d3f95b --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/atan.b b/contrib/bc/Test/atan.b new file mode 100644 index 0000000..e742279 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/checklib.b b/contrib/bc/Test/checklib.b new file mode 100644 index 0000000..44c1fac --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/div.b b/contrib/bc/Test/div.b new file mode 100644 index 0000000..3c7d377 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/exp.b b/contrib/bc/Test/exp.b new file mode 100644 index 0000000..92c482c --- /dev/null +++ b/contrib/bc/Test/exp.b @@ -0,0 +1,3 @@ +for (a=0; a<180; a+=.4) x=e(a) +x +quit diff --git a/contrib/bc/Test/fact.b b/contrib/bc/Test/fact.b new file mode 100644 index 0000000..995a26d --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/jn.b b/contrib/bc/Test/jn.b new file mode 100644 index 0000000..a4e0624 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/ln.b b/contrib/bc/Test/ln.b new file mode 100644 index 0000000..cd00232 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/mul.b b/contrib/bc/Test/mul.b new file mode 100644 index 0000000..722086f --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/raise.b b/contrib/bc/Test/raise.b new file mode 100644 index 0000000..ec6929d --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/signum b/contrib/bc/Test/signum new file mode 100644 index 0000000..9e27d2d --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/sine.b b/contrib/bc/Test/sine.b new file mode 100644 index 0000000..18c4b57 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/sqrt.b b/contrib/bc/Test/sqrt.b new file mode 100644 index 0000000..3fb548c --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/sqrt1.b b/contrib/bc/Test/sqrt1.b new file mode 100644 index 0000000..c3ca269 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/sqrt2.b b/contrib/bc/Test/sqrt2.b new file mode 100644 index 0000000..bd0eaad --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/testfn.b b/contrib/bc/Test/testfn.b new file mode 100644 index 0000000..7578fc5 --- /dev/null +++ b/contrib/bc/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/contrib/bc/Test/timetest b/contrib/bc/Test/timetest new file mode 100755 index 0000000..1a4d0ea --- /dev/null +++ b/contrib/bc/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/contrib/bc/acconfig.h b/contrib/bc/acconfig.h new file mode 100644 index 0000000..ff17f82 --- /dev/null +++ b/contrib/bc/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/contrib/bc/aclocal.m4 b/contrib/bc/aclocal.m4 new file mode 100644 index 0000000..102dc3e --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/Makefile.am b/contrib/bc/bc/Makefile.am new file mode 100644 index 0000000..9187339 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/Makefile.in b/contrib/bc/bc/Makefile.in new file mode 100644 index 0000000..18ebce0 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/bc.y b/contrib/bc/bc/bc.y new file mode 100644 index 0000000..403e326 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/bcdefs.h b/contrib/bc/bc/bcdefs.h new file mode 100644 index 0000000..260cd12 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/const.h b/contrib/bc/bc/const.h new file mode 100644 index 0000000..1a7c5b8 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/execute.c b/contrib/bc/bc/execute.c new file mode 100644 index 0000000..d2864d11 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/fix-libmath_h b/contrib/bc/bc/fix-libmath_h new file mode 100755 index 0000000..f973a8c --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/global.c b/contrib/bc/bc/global.c new file mode 100644 index 0000000..5d1205c --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/global.h b/contrib/bc/bc/global.h new file mode 100644 index 0000000..cf6945c --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/libmath.b b/contrib/bc/bc/libmath.b new file mode 100644 index 0000000..7bb6405 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/libmath.h b/contrib/bc/bc/libmath.h new file mode 100644 index 0000000..bf48f4b --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/load.c b/contrib/bc/bc/load.c new file mode 100644 index 0000000..40b8051 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/main.c b/contrib/bc/bc/main.c new file mode 100644 index 0000000..71b46a6 --- /dev/null +++ b/contrib/bc/bc/main.c @@ -0,0 +1,354 @@ +/* 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 + +$FreeBSD$ + +*************************************************************************/ + +#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/contrib/bc/bc/proto.h b/contrib/bc/bc/proto.h new file mode 100644 index 0000000..1e7311f --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/sbc.y b/contrib/bc/bc/sbc.y new file mode 100644 index 0000000..b1ff1d1 --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/scan.l b/contrib/bc/bc/scan.l new file mode 100644 index 0000000..8910c66 --- /dev/null +++ b/contrib/bc/bc/scan.l @@ -0,0 +1,374 @@ +%{ +/* $FreeBSD$ */ +/* 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; + +/* 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/contrib/bc/bc/storage.c b/contrib/bc/bc/storage.c new file mode 100644 index 0000000..10ebf5c --- /dev/null +++ b/contrib/bc/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/contrib/bc/bc/util.c b/contrib/bc/bc/util.c new file mode 100644 index 0000000..c305c2e --- /dev/null +++ b/contrib/bc/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/contrib/bc/config.h.in b/contrib/bc/config.h.in new file mode 100644 index 0000000..ebb9e34 --- /dev/null +++ b/contrib/bc/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/contrib/bc/configure b/contrib/bc/configure new file mode 100755 index 0000000..e5fc7d9 --- /dev/null +++ b/contrib/bc/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/contrib/bc/configure.in b/contrib/bc/configure.in new file mode 100644 index 0000000..5f982d3 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/Makefile.am b/contrib/bc/dc/Makefile.am new file mode 100644 index 0000000..99164ba --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/Makefile.in b/contrib/bc/dc/Makefile.in new file mode 100644 index 0000000..0772dd6 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/array.c b/contrib/bc/dc/array.c new file mode 100644 index 0000000..d97f716 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/dc-proto.h b/contrib/bc/dc/dc-proto.h new file mode 100644 index 0000000..f0ac28b --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/dc-regdef.h b/contrib/bc/dc/dc-regdef.h new file mode 100644 index 0000000..540268c --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/dc.c b/contrib/bc/dc/dc.c new file mode 100644 index 0000000..a72644c --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/dc.h b/contrib/bc/dc/dc.h new file mode 100644 index 0000000..3300f44 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/eval.c b/contrib/bc/dc/eval.c new file mode 100644 index 0000000..21592d9 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/misc.c b/contrib/bc/dc/misc.c new file mode 100644 index 0000000..fa94de1 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/numeric.c b/contrib/bc/dc/numeric.c new file mode 100644 index 0000000..6086be5 --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/stack.c b/contrib/bc/dc/stack.c new file mode 100644 index 0000000..1d8a9bf --- /dev/null +++ b/contrib/bc/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/contrib/bc/dc/string.c b/contrib/bc/dc/string.c new file mode 100644 index 0000000..a7f79a4 --- /dev/null +++ b/contrib/bc/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/contrib/bc/doc/Makefile.am b/contrib/bc/doc/Makefile.am new file mode 100644 index 0000000..a729cee --- /dev/null +++ b/contrib/bc/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/contrib/bc/doc/Makefile.in b/contrib/bc/doc/Makefile.in new file mode 100644 index 0000000..840d007 --- /dev/null +++ b/contrib/bc/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/contrib/bc/doc/bc.1 b/contrib/bc/doc/bc.1 new file mode 100644 index 0000000..bb19594 --- /dev/null +++ b/contrib/bc/doc/bc.1 @@ -0,0 +1,793 @@ +.\" +.\" 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 +.\" +.\" $FreeBSD$ +.\" +.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 +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 environment 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 specifying 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/contrib/bc/doc/bc.texi b/contrib/bc/doc/bc.texi new file mode 100644 index 0000000..a7cb9f6 --- /dev/null +++ b/contrib/bc/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/contrib/bc/doc/dc.1 b/contrib/bc/doc/dc.1 new file mode 100644 index 0000000..adaf5d0 --- /dev/null +++ b/contrib/bc/doc/dc.1 @@ -0,0 +1,490 @@ +.\" +.\" 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 +.\" +.\" $FreeBSD$ +.\" +.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/contrib/bc/doc/dc.texi b/contrib/bc/doc/dc.texi new file mode 100644 index 0000000..0a4d973 --- /dev/null +++ b/contrib/bc/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/contrib/bc/h/bcdefs.h b/contrib/bc/h/bcdefs.h new file mode 100644 index 0000000..0e51b2b --- /dev/null +++ b/contrib/bc/h/bcdefs.h @@ -0,0 +1,166 @@ +/* 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, 675 Mass Ave, Cambridge, MA 02139, USA. + + You may contact the author by: + e-mail: phil@cs.wwu.edu + 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 + +/* 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[BC_MAX_SEGS]; + 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; + diff --git a/contrib/bc/h/const.h b/contrib/bc/h/const.h new file mode 100644 index 0000000..1ed1465 --- /dev/null +++ b/contrib/bc/h/const.h @@ -0,0 +1,101 @@ +/* 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, 675 Mass Ave, Cambridge, MA 02139, USA. + + You may contact the author by: + e-mail: phil@cs.wwu.edu + 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_MAX_SEGS 16 /* Code segments. */ +#define BC_SEG_SIZE 1024 +#define BC_SEG_LOG 10 + +/* 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 + +/* Include the version definition. */ +#include "version.h" diff --git a/contrib/bc/h/getopt.h b/contrib/bc/h/getopt.h new file mode 100644 index 0000000..f3696d9 --- /dev/null +++ b/contrib/bc/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/contrib/bc/h/global.h b/contrib/bc/h/global.h new file mode 100644 index 0000000..bc431dc --- /dev/null +++ b/contrib/bc/h/global.h @@ -0,0 +1,147 @@ +/* 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, 675 Mass Ave, Cambridge, MA 02139, USA. + + You may contact the author by: + e-mail: phil@cs.wwu.edu + 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; +#ifdef READLINE +EXTERN int n_history; +#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; + +/* defined in number.c */ +extern bc_num _zero_; +extern bc_num _one_; + +/* For use with getopt. Do not declare them here.*/ +extern int optind; + diff --git a/contrib/bc/h/number.h b/contrib/bc/h/number.h new file mode 100644 index 0000000..8d78120 --- /dev/null +++ b/contrib/bc/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/contrib/bc/h/proto.h b/contrib/bc/h/proto.h new file mode 100644 index 0000000..016a166 --- /dev/null +++ b/contrib/bc/h/proto.h @@ -0,0 +1,171 @@ +/* proto.h: Prototype function definitions for "external" functions. */ + +/* 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, 675 Mass Ave, Cambridge, MA 02139, USA. + + You may contact the author by: + e-mail: phil@cs.wwu.edu + 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(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 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 main, (int argc , char *argv [])); +_PROTOTYPE(int open_new_file, (void)); +_PROTOTYPE(void new_yy_file, (FILE *file)); +_PROTOTYPE(void use_quit, (int)); + +/* From number.c */ +_PROTOTYPE(void free_num, (bc_num *num)); +_PROTOTYPE(bc_num new_num, (int length, int scale)); +_PROTOTYPE(void init_numbers, (void)); +_PROTOTYPE(bc_num copy_num, (bc_num num)); +_PROTOTYPE(void init_num, (bc_num *num)); +_PROTOTYPE(void str2num, (bc_num *num, char *str, int scale)); +_PROTOTYPE(char *num2str, (bc_num num)); +_PROTOTYPE(void int2num, (bc_num *num, int val)); +_PROTOTYPE(long num2long, (bc_num num)); +_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2)); +_PROTOTYPE(char is_zero, (bc_num num)); +_PROTOTYPE(char 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 out_long, (long val, int size, int space, + void (*out_char)(int))); +_PROTOTYPE(void out_num, (bc_num num, int o_base, void (* out_char)(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)); + +/* Other things... */ +#ifndef HAVE_UNISTD_H +_PROTOTYPE (int getopt, (int, char *[], CONST char *)); +#endif diff --git a/contrib/bc/h/version.h b/contrib/bc/h/version.h new file mode 100644 index 0000000..b98222f --- /dev/null +++ b/contrib/bc/h/version.h @@ -0,0 +1,28 @@ +/* version.h: version information for GNU bc and GNU dc */ + +/* This file is part of GNU bc and GNU 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.; 675 Mass Ave. Cambridge, MA 02139, USA. + */ + +#define BC_VERSION \ +"bc 1.05\n\ +Copyright 1991, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc." + +#define DC_VERSION \ +"dc 1.2 (GNU bc 1.05)\n\ +Copyright 1994, 1997, 1998 Free Software Foundation, Inc." diff --git a/contrib/bc/install-sh b/contrib/bc/install-sh new file mode 100755 index 0000000..ab74c88 --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/Makefile.am b/contrib/bc/lib/Makefile.am new file mode 100644 index 0000000..6f74b4d --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/Makefile.in b/contrib/bc/lib/Makefile.in new file mode 100644 index 0000000..5ffa593 --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/getopt.c b/contrib/bc/lib/getopt.c new file mode 100644 index 0000000..23ce064 --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/getopt1.c b/contrib/bc/lib/getopt1.c new file mode 100644 index 0000000..de8e2ad --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/number.c b/contrib/bc/lib/number.c new file mode 100644 index 0000000..1f913d5 --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/testmul.c b/contrib/bc/lib/testmul.c new file mode 100644 index 0000000..f7044d6 --- /dev/null +++ b/contrib/bc/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/contrib/bc/lib/vfprintf.c b/contrib/bc/lib/vfprintf.c new file mode 100644 index 0000000..ad53d0c --- /dev/null +++ b/contrib/bc/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/contrib/bc/missing b/contrib/bc/missing new file mode 100755 index 0000000..e4b838c --- /dev/null +++ b/contrib/bc/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/contrib/bc/mkinstalldirs b/contrib/bc/mkinstalldirs new file mode 100755 index 0000000..cc8783e --- /dev/null +++ b/contrib/bc/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/contrib/bc/stamp-h.in b/contrib/bc/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/contrib/bc/stamp-h.in @@ -0,0 +1 @@ +timestamp |