Import GNU bc 1.04
PR: 4183
This commit is contained in:
commit
17f33912d7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/bc/dist/; revision=35516 svn path=/vendor/bc/1.0.4/; revision=35518; tag=vendor/misc-GNU/bc/1.0.4
4
contrib/bc/AUTHORS
Normal file
4
contrib/bc/AUTHORS
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Phil Nelson <phil@cs.wwu.edu> wrote bc, including the number.c
|
||||||
|
source in the "lib" directory.
|
||||||
|
|
||||||
|
Ken Pizzini wrote dc.
|
341
contrib/bc/COPYING
Normal file
341
contrib/bc/COPYING
Normal file
@ -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.
|
||||||
|
|
694
contrib/bc/ChangeLog
Normal file
694
contrib/bc/ChangeLog
Normal file
@ -0,0 +1,694 @@
|
|||||||
|
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
|
||||||
|
|
16
contrib/bc/Examples/ckbook.b
Normal file
16
contrib/bc/Examples/ckbook.b
Normal file
@ -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
|
53
contrib/bc/Examples/pi.b
Normal file
53
contrib/bc/Examples/pi.b
Normal file
@ -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"
|
||||||
|
}
|
32
contrib/bc/Examples/primes.b
Normal file
32
contrib/bc/Examples/primes.b
Normal file
@ -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"
|
40
contrib/bc/Examples/twins.b
Normal file
40
contrib/bc/Examples/twins.b
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
}
|
176
contrib/bc/INSTALL
Normal file
176
contrib/bc/INSTALL
Normal file
@ -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.
|
||||||
|
|
9
contrib/bc/Makefile.am
Normal file
9
contrib/bc/Makefile.am
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
SUBDIRS = lib bc dc doc
|
||||||
|
|
||||||
|
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
|
296
contrib/bc/Makefile.in
Normal file
296
contrib/bc/Makefile.in
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
# Makefile.in generated automatically by automake 1.1n from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
transform = @program_transform_name@
|
||||||
|
|
||||||
|
NORMAL_INSTALL = true
|
||||||
|
PRE_INSTALL = true
|
||||||
|
POST_INSTALL = true
|
||||||
|
NORMAL_UNINSTALL = true
|
||||||
|
PRE_UNINSTALL = true
|
||||||
|
POST_UNINSTALL = true
|
||||||
|
CC = @CC@
|
||||||
|
LEX = @LEX@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
YACC = @YACC@
|
||||||
|
|
||||||
|
SUBDIRS = lib bc dc doc
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
CONFIG_HEADER_IN = config.h.in
|
||||||
|
CONFIG_HEADER_FULL = config.h
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = config.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
|
||||||
|
Makefile.in NEWS acconfig.h aclocal.m4 config.h.in configure \
|
||||||
|
configure.in install-sh missing mkinstalldirs stamp-h.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP = --best
|
||||||
|
default: all
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||||
|
|
||||||
|
$(srcdir)/aclocal.m4: configure.in
|
||||||
|
cd $(srcdir) && $(ACLOCAL)
|
||||||
|
|
||||||
|
config.status: configure
|
||||||
|
$(SHELL) ./config.status --recheck
|
||||||
|
$(srcdir)/configure: configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
|
||||||
|
cd $(srcdir) && $(AUTOCONF)
|
||||||
|
|
||||||
|
$(CONFIG_HEADER): stamp-h
|
||||||
|
stamp-h: $(CONFIG_HEADER_IN) $(top_builddir)/config.status
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES= CONFIG_HEADERS=$(CONFIG_HEADER_FULL) \
|
||||||
|
$(SHELL) ./config.status
|
||||||
|
@echo timestamp > stamp-h
|
||||||
|
$(srcdir)/$(CONFIG_HEADER_IN): stamp-h.in
|
||||||
|
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
|
||||||
|
cd $(top_srcdir) && $(AUTOHEADER)
|
||||||
|
echo timestamp > $(srcdir)/stamp-h.in
|
||||||
|
|
||||||
|
mostlyclean-hdr:
|
||||||
|
|
||||||
|
clean-hdr:
|
||||||
|
|
||||||
|
distclean-hdr:
|
||||||
|
rm -f $(CONFIG_HEADER)
|
||||||
|
|
||||||
|
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 \
|
||||||
|
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||||
|
maintainer-clean-recursive:
|
||||||
|
@for subdir in $(SUBDIRS); do \
|
||||||
|
target=`echo $@ | sed s/-recursive//`; \
|
||||||
|
echo "Making $$target in $$subdir"; \
|
||||||
|
(cd $$subdir && $(MAKE) $$target) \
|
||||||
|
|| case "$(MFLAGS)" in *k*) fail=yes;; *) exit 1;; esac; \
|
||||||
|
done && test -z "$$fail"
|
||||||
|
tags-recursive:
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
(cd $$subdir && $(MAKE) tags); \
|
||||||
|
done
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
|
||||||
|
ID: $(HEADERS) $(SOURCES)
|
||||||
|
here=`pwd` && cd $(srcdir) && mkid -f$$here/ID $(SOURCES) $(HEADERS)
|
||||||
|
|
||||||
|
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||||
|
done; \
|
||||||
|
test -z "$(ETAGS_ARGS)config.h.in$(SOURCES)$(HEADERS)$$tags" \
|
||||||
|
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $(SOURCES) $(HEADERS) -o $$here/TAGS)
|
||||||
|
|
||||||
|
mostlyclean-tags:
|
||||||
|
|
||||||
|
clean-tags:
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
rm -f TAGS ID
|
||||||
|
|
||||||
|
maintainer-clean-tags:
|
||||||
|
|
||||||
|
distdir = $(PACKAGE)-$(VERSION)
|
||||||
|
# This target untars the dist file and tries a VPATH configuration. Then
|
||||||
|
# it guarantees that the distribution is self-contained by making another
|
||||||
|
# tarfile.
|
||||||
|
distcheck: dist
|
||||||
|
rm -rf $(distdir)
|
||||||
|
GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz
|
||||||
|
mkdir $(distdir)/=build
|
||||||
|
mkdir $(distdir)/=inst
|
||||||
|
dc_install_base=`cd $(distdir)/=inst && pwd`; \
|
||||||
|
cd $(distdir)/=build \
|
||||||
|
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
|
||||||
|
&& $(MAKE) \
|
||||||
|
&& $(MAKE) dvi \
|
||||||
|
&& $(MAKE) check \
|
||||||
|
&& $(MAKE) install \
|
||||||
|
&& $(MAKE) installcheck \
|
||||||
|
&& $(MAKE) dist
|
||||||
|
rm -rf $(distdir)
|
||||||
|
@echo "========================"; \
|
||||||
|
echo "$(distdir).tar.gz is ready for distribution"; \
|
||||||
|
echo "========================"
|
||||||
|
dist: distdir
|
||||||
|
-chmod -R a+r $(distdir)
|
||||||
|
GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
|
||||||
|
rm -rf $(distdir)
|
||||||
|
dist-all: distdir
|
||||||
|
-chmod -R a+r $(distdir)
|
||||||
|
GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir)
|
||||||
|
rm -rf $(distdir)
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
rm -rf $(distdir)
|
||||||
|
mkdir $(distdir)
|
||||||
|
-chmod 755 $(distdir)
|
||||||
|
@for file in $(DISTFILES); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||||
|
done
|
||||||
|
for subdir in $(SUBDIRS); do \
|
||||||
|
test -d $(distdir)/$$subdir \
|
||||||
|
|| mkdir $(distdir)/$$subdir \
|
||||||
|
|| exit 1; \
|
||||||
|
chmod 755 $(distdir)/$$subdir; \
|
||||||
|
(cd $$subdir && $(MAKE) distdir=../$(distdir)/$$subdir distdir) \
|
||||||
|
|| exit 1; \
|
||||||
|
done
|
||||||
|
$(MAKE) distdir="$(distdir)" dist-hook
|
||||||
|
info: info-recursive
|
||||||
|
dvi: dvi-recursive
|
||||||
|
check: all-am
|
||||||
|
$(MAKE) check-recursive
|
||||||
|
installcheck: installcheck-recursive
|
||||||
|
all-recursive-am: $(CONFIG_HEADER)
|
||||||
|
$(MAKE) all-recursive
|
||||||
|
|
||||||
|
all-am: Makefile config.h
|
||||||
|
|
||||||
|
install-exec: install-exec-recursive
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install-data: install-data-recursive
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install: install-recursive
|
||||||
|
@:
|
||||||
|
|
||||||
|
uninstall: uninstall-recursive
|
||||||
|
|
||||||
|
all: all-recursive-am all-am
|
||||||
|
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||||
|
installdirs: installdirs-recursive
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
rm -f Makefile $(DISTCLEANFILES)
|
||||||
|
rm -f config.cache config.log stamp-h
|
||||||
|
test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||||
|
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||||
|
mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic
|
||||||
|
|
||||||
|
clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
|
||||||
|
|
||||||
|
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \
|
||||||
|
maintainer-clean-generic distclean-am
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-recursive mostlyclean-am
|
||||||
|
|
||||||
|
clean: clean-recursive clean-am
|
||||||
|
|
||||||
|
distclean: distclean-recursive distclean-am
|
||||||
|
rm -f config.status
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-recursive maintainer-clean-am
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
rm -f config.status
|
||||||
|
|
||||||
|
.PHONY: default mostlyclean-hdr distclean-hdr clean-hdr \
|
||||||
|
maintainer-clean-hdr 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 dvi \
|
||||||
|
installcheck all-recursive-am all-am install-exec install-data install \
|
||||||
|
uninstall all 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
|
||||||
|
|
||||||
|
# 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:
|
31
contrib/bc/NEWS
Normal file
31
contrib/bc/NEWS
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
This is GNU bc version 1.04. (And dc version 1.0.4)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
57
contrib/bc/README
Normal file
57
contrib/bc/README
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
-------- 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.
|
40
contrib/bc/Test/BUG.bc
Normal file
40
contrib/bc/Test/BUG.bc
Normal file
@ -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 */
|
565
contrib/bc/Test/TESTS.bc
Normal file
565
contrib/bc/Test/TESTS.bc
Normal file
@ -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
|
||||||
|
|
||||||
|
|
14
contrib/bc/Test/array.b
Normal file
14
contrib/bc/Test/array.b
Normal file
@ -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);
|
||||||
|
|
30
contrib/bc/Test/arrayp.b
Normal file
30
contrib/bc/Test/arrayp.b
Normal file
@ -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
|
||||||
|
|
16
contrib/bc/Test/aryprm.b
Normal file
16
contrib/bc/Test/aryprm.b
Normal file
@ -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[]);
|
5
contrib/bc/Test/atan.b
Normal file
5
contrib/bc/Test/atan.b
Normal file
@ -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
|
109
contrib/bc/Test/checklib.b
Normal file
109
contrib/bc/Test/checklib.b
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
|
8
contrib/bc/Test/div.b
Normal file
8
contrib/bc/Test/div.b
Normal file
@ -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
|
||||||
|
|
3
contrib/bc/Test/exp.b
Normal file
3
contrib/bc/Test/exp.b
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
for (a=0; a<150; a++) x=e(a)
|
||||||
|
x
|
||||||
|
quit
|
13
contrib/bc/Test/fact.b
Normal file
13
contrib/bc/Test/fact.b
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
define f (x) {
|
||||||
|
|
||||||
|
if (x<=1) return(1)
|
||||||
|
return (f(x-1)*x)
|
||||||
|
}
|
||||||
|
|
||||||
|
"Here we go"
|
||||||
|
for (a=1; a<100; a++) b+=f(a)/a
|
||||||
|
"
|
||||||
|
"
|
||||||
|
"b=";b
|
||||||
|
quit
|
||||||
|
|
6
contrib/bc/Test/jn.b
Normal file
6
contrib/bc/Test/jn.b
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
scale = 30
|
||||||
|
for (a=0; a<5; a=a+2) {
|
||||||
|
for (b=0; b<100; b=b+10) x=j(a,b)
|
||||||
|
}
|
||||||
|
x
|
||||||
|
quit
|
3
contrib/bc/Test/ln.b
Normal file
3
contrib/bc/Test/ln.b
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
for (a=1; a<10000000000000000000000000000; a = a*2) x=l(a)
|
||||||
|
x
|
||||||
|
quit
|
7
contrib/bc/Test/mul.b
Normal file
7
contrib/bc/Test/mul.b
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
scale = 20
|
||||||
|
for (i=0; i<1000; i++) {
|
||||||
|
for (j=1; j<100; j++) b=i*j
|
||||||
|
}
|
||||||
|
b
|
||||||
|
quit
|
||||||
|
|
3
contrib/bc/Test/raise.b
Normal file
3
contrib/bc/Test/raise.b
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
for (i=0; i<1000; i++) a = 2^i;
|
||||||
|
a
|
||||||
|
quit
|
87
contrib/bc/Test/signum
Normal file
87
contrib/bc/Test/signum
Normal file
@ -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
|
||||||
|
"
|
5
contrib/bc/Test/sine.b
Normal file
5
contrib/bc/Test/sine.b
Normal file
@ -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
|
13
contrib/bc/Test/sqrt.b
Normal file
13
contrib/bc/Test/sqrt.b
Normal file
@ -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
|
13
contrib/bc/Test/sqrt1.b
Normal file
13
contrib/bc/Test/sqrt1.b
Normal file
@ -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
|
10
contrib/bc/Test/sqrt2.b
Normal file
10
contrib/bc/Test/sqrt2.b
Normal file
@ -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
|
47
contrib/bc/Test/testfn.b
Normal file
47
contrib/bc/Test/testfn.b
Normal file
@ -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;
|
||||||
|
|
||||||
|
}
|
14
contrib/bc/Test/timetest
Executable file
14
contrib/bc/Test/timetest
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Time the functions.
|
||||||
|
#
|
||||||
|
BC=../bc
|
||||||
|
SYSBC=/usr/bin/bc
|
||||||
|
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
|
||||||
|
do
|
||||||
|
echo Timing $file with $prog
|
||||||
|
time $prog -l $file
|
||||||
|
done
|
||||||
|
done
|
15
contrib/bc/acconfig.h
Normal file
15
contrib/bc/acconfig.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* PACKAGE name */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Package VERSION number */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* define if the math lib is to be loaded from a file. */
|
||||||
|
#undef BC_MATH_FILE
|
||||||
|
|
||||||
|
/* Define to use the readline library. */
|
||||||
|
#undef READLINE
|
||||||
|
|
||||||
|
/* Define to `size_t' if <sys/types.h> and <stddef.h> don't define. */
|
||||||
|
#undef ptrdiff_t
|
||||||
|
|
100
contrib/bc/aclocal.m4
vendored
Normal file
100
contrib/bc/aclocal.m4
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
dnl aclocal.m4 generated automatically by aclocal 1.1n
|
||||||
|
|
||||||
|
# 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([AM_PROG_INSTALL])
|
||||||
|
PACKAGE=[$1]
|
||||||
|
AC_SUBST(PACKAGE)
|
||||||
|
VERSION=[$2]
|
||||||
|
AC_SUBST(VERSION)
|
||||||
|
ifelse([$3],,
|
||||||
|
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
|
||||||
|
AC_DEFINE_UNQUOTED(VERSION, "$VERSION"))
|
||||||
|
AM_SANITY_CHECK
|
||||||
|
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_PROG_MAKE_SET])
|
||||||
|
|
||||||
|
|
||||||
|
# serial 1
|
||||||
|
|
||||||
|
AC_DEFUN(AM_PROG_INSTALL,
|
||||||
|
[AC_REQUIRE([AC_PROG_INSTALL])
|
||||||
|
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
|
||||||
|
AC_SUBST(INSTALL_SCRIPT)dnl
|
||||||
|
])
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
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.
|
||||||
|
if ($2 --version) > /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
|
||||||
|
test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl
|
||||||
|
changequote([,]))])
|
||||||
|
|
46
contrib/bc/bc/Makefile.am
Normal file
46
contrib/bc/bc/Makefile.am
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
## 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 fix-libmath_h libmath.b sbc.y
|
||||||
|
noinst_HEADERS = libmath.h
|
||||||
|
|
||||||
|
DISTCLEANFILES = sbc sbc.c sbc.h
|
||||||
|
MAINTAINERCLEANFILES = libmath.h bc.c bc.h
|
||||||
|
|
||||||
|
datadir = $(prefix)/@DATADIRNAME@
|
||||||
|
|
||||||
|
INCLUDES = -I$(srcdir) -I$(srcdir)/../h
|
||||||
|
LDADD = ../lib/libbc.a @LEXLIB@
|
||||||
|
|
||||||
|
$(PROGRAMS): $(LDADD)
|
||||||
|
|
||||||
|
scan.o: bc.h
|
||||||
|
global.o: libmath.h
|
||||||
|
|
||||||
|
libmath.h: libmath.b
|
||||||
|
echo \"\" > libmath.h
|
||||||
|
$(MAKE) fbc
|
||||||
|
./fbc -c $(srcdir)/libmath.b </dev/null >libmath.h
|
||||||
|
$(srcdir)/fix-libmath_h
|
||||||
|
rm -f ./fbc
|
||||||
|
|
||||||
|
install-data-local:
|
||||||
|
if grep -s "define BC_MATH_FILE" ../config.h; \
|
||||||
|
then $(mkinstalldirs) $(libdir); \
|
||||||
|
rm -f $(libdir)/libmath.b; \
|
||||||
|
$(INSTALL_DATA) $(srcdir)/libmath.b $(libdir); \
|
||||||
|
chmod 444 $(libdir)/libmath.b; \
|
||||||
|
else true; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
fbcOBJ = main.o bc.o scan.o execute.o global.o load.o storage.o util.o
|
||||||
|
fbc: $(fbcOBJ)
|
||||||
|
$(LINK) $(fbcOBJ) $(LDADD) $(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) $(LDADD) $(LIBS)
|
294
contrib/bc/bc/Makefile.in
Normal file
294
contrib/bc/bc/Makefile.in
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
# Makefile.in generated automatically by automake 1.1n from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
|
||||||
|
bindir = @bindir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
libdir = @libdir@
|
||||||
|
infodir = @infodir@
|
||||||
|
mandir = @mandir@
|
||||||
|
includedir = @includedir@
|
||||||
|
oldincludedir = /usr/include
|
||||||
|
|
||||||
|
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@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
transform = @program_transform_name@
|
||||||
|
|
||||||
|
NORMAL_INSTALL = true
|
||||||
|
PRE_INSTALL = true
|
||||||
|
POST_INSTALL = true
|
||||||
|
NORMAL_UNINSTALL = true
|
||||||
|
PRE_UNINSTALL = true
|
||||||
|
POST_UNINSTALL = true
|
||||||
|
CC = @CC@
|
||||||
|
LEX = @LEX@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
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 fix-libmath_h libmath.b sbc.y
|
||||||
|
noinst_HEADERS = libmath.h
|
||||||
|
|
||||||
|
DISTCLEANFILES = sbc sbc.c sbc.h
|
||||||
|
MAINTAINERCLEANFILES = libmath.h bc.c bc.h
|
||||||
|
|
||||||
|
datadir = $(prefix)/@DATADIRNAME@
|
||||||
|
|
||||||
|
INCLUDES = -I$(srcdir) -I$(srcdir)/../h
|
||||||
|
LDADD = ../lib/libbc.a @LEXLIB@
|
||||||
|
|
||||||
|
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@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||||
|
LINK = $(CC) $(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 = --best
|
||||||
|
SOURCES = $(bc_SOURCES)
|
||||||
|
OBJECTS = $(bc_OBJECTS)
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .c .o .y .l
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu bc/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
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) $(bindir)
|
||||||
|
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
if test -f $$p; then \
|
||||||
|
echo " $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed '$(transform)'`"; \
|
||||||
|
$(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed '$(transform)'`; \
|
||||||
|
else :; fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-binPROGRAMS:
|
||||||
|
$(NORMAL_UNINSTALL)
|
||||||
|
list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
rm -f $(bindir)/`echo $$p|sed '$(transform)'`; \
|
||||||
|
done
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(COMPILE) -c $<
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
rm -f *.o 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)
|
||||||
|
.y.c:
|
||||||
|
$(YACC) $(YFLAGS) $< && mv y.tab.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
|
||||||
|
.l.c:
|
||||||
|
$(LEX) $(LFLAGS) $< && mv $(LEX_OUTPUT_ROOT).c $@
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
|
||||||
|
ID: $(HEADERS) $(SOURCES)
|
||||||
|
here=`pwd` && cd $(srcdir) && mkid -f$$here/ID $(SOURCES) $(HEADERS)
|
||||||
|
|
||||||
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||||
|
done; \
|
||||||
|
test -z "$(ETAGS_ARGS)$(SOURCES)$(HEADERS)$$tags" \
|
||||||
|
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $(SOURCES) $(HEADERS) -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); \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||||
|
done
|
||||||
|
info:
|
||||||
|
dvi:
|
||||||
|
check: all
|
||||||
|
$(MAKE)
|
||||||
|
installcheck:
|
||||||
|
install-exec: install-binPROGRAMS
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install-data: install-data-local
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install: install-exec install-data all
|
||||||
|
@:
|
||||||
|
|
||||||
|
uninstall: uninstall-binPROGRAMS
|
||||||
|
|
||||||
|
all: $(PROGRAMS) $(HEADERS) Makefile
|
||||||
|
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||||
|
installdirs:
|
||||||
|
$(mkinstalldirs) $(bindir)
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
rm -f Makefile $(DISTCLEANFILES)
|
||||||
|
rm -f config.cache config.log stamp-h
|
||||||
|
test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||||
|
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||||
|
mostlyclean: mostlyclean-binPROGRAMS mostlyclean-compile \
|
||||||
|
mostlyclean-tags mostlyclean-generic
|
||||||
|
|
||||||
|
clean: clean-binPROGRAMS clean-compile clean-tags clean-generic \
|
||||||
|
mostlyclean
|
||||||
|
|
||||||
|
distclean: distclean-binPROGRAMS distclean-compile distclean-tags \
|
||||||
|
distclean-generic clean
|
||||||
|
rm -f config.status
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-binPROGRAMS maintainer-clean-compile \
|
||||||
|
maintainer-clean-tags maintainer-clean-generic \
|
||||||
|
distclean
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
.PHONY: default 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 dvi installcheck \
|
||||||
|
install-exec install-data install uninstall all installdirs \
|
||||||
|
mostlyclean-generic distclean-generic clean-generic \
|
||||||
|
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
|
$(PROGRAMS): $(LDADD)
|
||||||
|
|
||||||
|
scan.o: bc.h
|
||||||
|
global.o: libmath.h
|
||||||
|
|
||||||
|
libmath.h: libmath.b
|
||||||
|
echo \"\" > libmath.h
|
||||||
|
$(MAKE) fbc
|
||||||
|
./fbc -c $(srcdir)/libmath.b </dev/null >libmath.h
|
||||||
|
$(srcdir)/fix-libmath_h
|
||||||
|
rm -f ./fbc
|
||||||
|
|
||||||
|
install-data-local:
|
||||||
|
if grep -s "define BC_MATH_FILE" ../config.h; \
|
||||||
|
then $(mkinstalldirs) $(libdir); \
|
||||||
|
rm -f $(libdir)/libmath.b; \
|
||||||
|
$(INSTALL_DATA) $(srcdir)/libmath.b $(libdir); \
|
||||||
|
chmod 444 $(libdir)/libmath.b; \
|
||||||
|
else true; \
|
||||||
|
fi
|
||||||
|
fbc: $(fbcOBJ)
|
||||||
|
$(LINK) $(fbcOBJ) $(LDADD) $(LIBS)
|
||||||
|
sbc.o: sbc.c
|
||||||
|
sbc: $(sbcOBJ)
|
||||||
|
$(LINK) $(sbcOBJ) $(LDADD) $(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:
|
1808
contrib/bc/bc/bc.c
Normal file
1808
contrib/bc/bc/bc.c
Normal file
File diff suppressed because it is too large
Load Diff
42
contrib/bc/bc/bc.h
Normal file
42
contrib/bc/bc/bc.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
typedef union {
|
||||||
|
char *s_value;
|
||||||
|
char c_value;
|
||||||
|
int i_value;
|
||||||
|
arg_list *a_value;
|
||||||
|
} YYSTYPE;
|
||||||
|
#define NEWLINE 258
|
||||||
|
#define AND 259
|
||||||
|
#define OR 260
|
||||||
|
#define NOT 261
|
||||||
|
#define STRING 262
|
||||||
|
#define NAME 263
|
||||||
|
#define NUMBER 264
|
||||||
|
#define ASSIGN_OP 265
|
||||||
|
#define REL_OP 266
|
||||||
|
#define INCR_DECR 267
|
||||||
|
#define Define 268
|
||||||
|
#define Break 269
|
||||||
|
#define Quit 270
|
||||||
|
#define Length 271
|
||||||
|
#define Return 272
|
||||||
|
#define For 273
|
||||||
|
#define If 274
|
||||||
|
#define While 275
|
||||||
|
#define Sqrt 276
|
||||||
|
#define Else 277
|
||||||
|
#define Scale 278
|
||||||
|
#define Ibase 279
|
||||||
|
#define Obase 280
|
||||||
|
#define Auto 281
|
||||||
|
#define Read 282
|
||||||
|
#define Warranty 283
|
||||||
|
#define Halt 284
|
||||||
|
#define Last 285
|
||||||
|
#define Continue 286
|
||||||
|
#define Print 287
|
||||||
|
#define Limits 288
|
||||||
|
#define UNARY_MINUS 289
|
||||||
|
#define History 290
|
||||||
|
|
||||||
|
|
||||||
|
extern YYSTYPE yylval;
|
637
contrib/bc/bc/bc.y
Normal file
637
contrib/bc/bc/bc.y
Normal file
@ -0,0 +1,637 @@
|
|||||||
|
%{
|
||||||
|
/* 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, 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 "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 grammer 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> NEWLINE 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 History
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
printf ("%s\n", BC_VERSION);
|
||||||
|
welcome ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| program input_item
|
||||||
|
;
|
||||||
|
input_item : semicolon_list NEWLINE
|
||||||
|
{ run_code (); }
|
||||||
|
| function
|
||||||
|
{ run_code (); }
|
||||||
|
| error NEWLINE
|
||||||
|
{
|
||||||
|
yyerrok;
|
||||||
|
init_gen ();
|
||||||
|
}
|
||||||
|
;
|
||||||
|
opt_newline : /* empty */
|
||||||
|
| NEWLINE
|
||||||
|
{ 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 NEWLINE
|
||||||
|
| statement_list NEWLINE 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
|
||||||
|
{ generate ("0R"); }
|
||||||
|
| Return '(' return_expression ')'
|
||||||
|
{ generate ("R"); }
|
||||||
|
| For
|
||||||
|
{
|
||||||
|
$1 = break_label;
|
||||||
|
break_label = next_label++;
|
||||||
|
}
|
||||||
|
'(' opt_expression ';'
|
||||||
|
{
|
||||||
|
if ($4 > 1)
|
||||||
|
warn ("Comparison in first for expression");
|
||||||
|
$4 = next_label++;
|
||||||
|
if ($4 < 0)
|
||||||
|
sprintf (genstr, "N%1d:", $4);
|
||||||
|
else
|
||||||
|
sprintf (genstr, "pN%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 > 1)
|
||||||
|
warn ("Comparison in third for expression");
|
||||||
|
if ($10 < 0)
|
||||||
|
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
|
||||||
|
'{' NEWLINE 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 /* NEWLINE */ '}'
|
||||||
|
{
|
||||||
|
generate ("0R]");
|
||||||
|
next_label = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
opt_parameter_list : /* empty */
|
||||||
|
{ $$ = NULL; }
|
||||||
|
| define_list
|
||||||
|
;
|
||||||
|
opt_auto_define_list : /* empty */
|
||||||
|
{ $$ = NULL; }
|
||||||
|
| Auto define_list NEWLINE
|
||||||
|
{ $$ = $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 > 1) 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 > 1) warn ("comparison in argument");
|
||||||
|
$$ = nextarg ($1,0,FALSE);
|
||||||
|
}
|
||||||
|
| argument_list ',' NAME '[' ']'
|
||||||
|
{
|
||||||
|
sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
|
||||||
|
generate (genstr);
|
||||||
|
$$ = nextarg ($1,1,FALSE);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
opt_expression : /* empty */
|
||||||
|
{
|
||||||
|
$$ = -1;
|
||||||
|
warn ("Missing expression in for statement");
|
||||||
|
}
|
||||||
|
| expression
|
||||||
|
;
|
||||||
|
return_expression : /* empty */
|
||||||
|
{
|
||||||
|
$$ = 0;
|
||||||
|
generate ("0");
|
||||||
|
}
|
||||||
|
| expression
|
||||||
|
{
|
||||||
|
if ($1 > 1)
|
||||||
|
warn ("comparison in return expresion");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
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 > 1) 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;
|
||||||
|
}
|
||||||
|
| 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;
|
||||||
|
}
|
||||||
|
| NOT expression
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
| expression '-' expression
|
||||||
|
{
|
||||||
|
generate ("-");
|
||||||
|
$$ = $1 | $3;
|
||||||
|
}
|
||||||
|
| expression '*' expression
|
||||||
|
{
|
||||||
|
generate ("*");
|
||||||
|
$$ = $1 | $3;
|
||||||
|
}
|
||||||
|
| expression '/' expression
|
||||||
|
{
|
||||||
|
generate ("/");
|
||||||
|
$$ = $1 | $3;
|
||||||
|
}
|
||||||
|
| expression '%' expression
|
||||||
|
{
|
||||||
|
generate ("%");
|
||||||
|
$$ = $1 | $3;
|
||||||
|
}
|
||||||
|
| expression '^' expression
|
||||||
|
{
|
||||||
|
generate ("^");
|
||||||
|
$$ = $1 | $3;
|
||||||
|
}
|
||||||
|
| '-' expression %prec UNARY_MINUS
|
||||||
|
{
|
||||||
|
generate ("n");
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
| 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 | 1; }
|
||||||
|
| 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; }
|
||||||
|
| History
|
||||||
|
{ $$ = 3;
|
||||||
|
warn ("History variable");
|
||||||
|
}
|
||||||
|
| Last
|
||||||
|
{ $$ = 4;
|
||||||
|
warn ("Last variable");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
786
contrib/bc/bc/execute.c
Normal file
786
contrib/bc/bc/execute.c
Normal file
@ -0,0 +1,786 @@
|
|||||||
|
/* execute.c - run a bc program. */
|
||||||
|
|
||||||
|
/* 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 "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;
|
||||||
|
{
|
||||||
|
int seg, offset;
|
||||||
|
|
||||||
|
seg = pc->pc_addr >> BC_SEG_LOG;
|
||||||
|
offset = pc->pc_addr++ % BC_SEG_SIZE;
|
||||||
|
return (functions[pc->pc_func].f_body[seg][offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
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);
|
||||||
|
out_num (temp->s_num, 10, out_char);
|
||||||
|
depth++;
|
||||||
|
temp = temp->s_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch ( inst )
|
||||||
|
{
|
||||||
|
|
||||||
|
case 'A' : /* increment array variable (Add one). */
|
||||||
|
var_name = byte(&pc);
|
||||||
|
if ((var_name & 0x80) != 0)
|
||||||
|
var_name = ((var_name << 8) & 0x7f) + 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 = !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 << 8) & 0x7f) + 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 << 8) & 0x7f) + 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 << 8) & 0x7f) + 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 << 8) & 0x7f) + byte(&pc);
|
||||||
|
store_array (var_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T' : /* Test tos for zero */
|
||||||
|
c_code = 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. */
|
||||||
|
out_num (ex_stack->s_num, o_base, out_char);
|
||||||
|
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 )
|
||||||
|
int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
|
||||||
|
else
|
||||||
|
int2num (&ex_stack->s_num, ex_stack->s_num->n_len
|
||||||
|
+ ex_stack->s_num->n_scale);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S': /* Scale function. */
|
||||||
|
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 << 8) & 0x7f) + 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 << 8) & 0x7f) + byte(&pc);
|
||||||
|
incr_var (var_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l' : /* load variable */
|
||||||
|
var_name = byte(&pc);
|
||||||
|
if ((var_name & 0x80) != 0)
|
||||||
|
var_name = ((var_name << 8) & 0x7f) + 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 << 8) & 0x7f) + 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 = is_zero (ex_stack->s_num);
|
||||||
|
assign (c_code);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&' : /* compare greater than */
|
||||||
|
if (check_stack(2))
|
||||||
|
{
|
||||||
|
c_code = !is_zero (ex_stack->s_next->s_num)
|
||||||
|
&& !is_zero (ex_stack->s_num);
|
||||||
|
pop ();
|
||||||
|
assign (c_code);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '|' : /* compare greater than */
|
||||||
|
if (check_stack(2))
|
||||||
|
{
|
||||||
|
c_code = !is_zero (ex_stack->s_next->s_num)
|
||||||
|
|| !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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
init_num (&temp_num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rt_error ("Divide by zero");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%' : /* remainder */
|
||||||
|
if (check_stack(2))
|
||||||
|
{
|
||||||
|
if (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);
|
||||||
|
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 (is_zero (ex_stack->s_next->s_num) && is_neg (ex_stack->s_num))
|
||||||
|
rt_error ("divide by zero");
|
||||||
|
pop();
|
||||||
|
pop();
|
||||||
|
push_num (temp_num);
|
||||||
|
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(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 */
|
||||||
|
init_num (&temp);
|
||||||
|
init_num (&result);
|
||||||
|
init_num (&mult);
|
||||||
|
build = copy_num (_zero_);
|
||||||
|
negative = FALSE;
|
||||||
|
|
||||||
|
/* The conversion base. */
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
free_num (&result);
|
||||||
|
free_num (&temp);
|
||||||
|
divisor = copy_num (_one_);
|
||||||
|
result = copy_num (_zero_);
|
||||||
|
digits = 0;
|
||||||
|
while (in_ch < 16)
|
||||||
|
{
|
||||||
|
bc_multiply (result, mult, &result, 0);
|
||||||
|
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);
|
||||||
|
free_num (&temp);
|
||||||
|
free_num (&result);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
init_num (&build);
|
||||||
|
int2num (&build, inchar);
|
||||||
|
push_num (build);
|
||||||
|
inchar = byte(pc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the new number. */
|
||||||
|
if (kdigits == 0)
|
||||||
|
{
|
||||||
|
build = new_num (1,kscale);
|
||||||
|
ptr = build->n_value;
|
||||||
|
*ptr++ = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build = 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;
|
||||||
|
{
|
||||||
|
free_num (&ex_stack->s_num);
|
||||||
|
if (c_code)
|
||||||
|
ex_stack->s_num = copy_num (_one_);
|
||||||
|
else
|
||||||
|
ex_stack->s_num = copy_num (_zero_);
|
||||||
|
}
|
8
contrib/bc/bc/fix-libmath_h
Executable file
8
contrib/bc/bc/fix-libmath_h
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
ed libmath.h <<EOS-EOS
|
||||||
|
1,1s/^/"/
|
||||||
|
1,\$s/\$/\\\\/
|
||||||
|
\$,\$d
|
||||||
|
\$,\$s/\\\\\$/"/
|
||||||
|
w
|
||||||
|
q
|
||||||
|
EOS-EOS
|
42
contrib/bc/bc/global.c
Normal file
42
contrib/bc/bc/global.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* global.c: This defines the global variables. */
|
||||||
|
|
||||||
|
/* 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 "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"
|
||||||
|
|
||||||
|
#ifndef BC_MATH_FILE
|
||||||
|
CONST char libmath[] =
|
||||||
|
#include "libmath.h"
|
||||||
|
;
|
||||||
|
#endif
|
279
contrib/bc/bc/libmath.b
Normal file
279
contrib/bc/bc/libmath.b
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/* 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, 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
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
scale += 1;
|
||||||
|
v = s(x+a(1)*2);
|
||||||
|
scale -= 1;
|
||||||
|
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, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
/* The Loop.... */
|
||||||
|
for (i=1; 1; i++) {
|
||||||
|
e = e * s / i / (n+i);
|
||||||
|
if (e == 0) {
|
||||||
|
scale = z
|
||||||
|
if (m) return (-f*v/1);
|
||||||
|
return (f*v/1);
|
||||||
|
}
|
||||||
|
v += e;
|
||||||
|
}
|
||||||
|
}
|
40
contrib/bc/bc/libmath.h
Normal file
40
contrib/bc/bc/libmath.h
Normal file
@ -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[l2:1+s2:pl5:1C4,0:K2:*+C3,0:s13:pl2:1-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,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:1s9:pK2: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:*s2:p1s10:\
|
||||||
|
pN8:1B9:J7:N10:l10:i10:pJ8:N9:l8:l15:*l10:/l12:l10:+/s8:pl8:0\
|
||||||
|
=Z11:l14:s2:pl11:Z12:l9:nl13:*1/RN12:l9:l13:*1/RN11:l13:l8:+s13:\
|
||||||
|
pJ10:N7:0R]@r"
|
348
contrib/bc/bc/load.c
Normal file
348
contrib/bc/bc/load.c
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
/* load.c: This code "loads" code into the code segments. */
|
||||||
|
|
||||||
|
/* 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 "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 seg, offset, func;
|
||||||
|
|
||||||
|
/* If there was an error, don't continue. */
|
||||||
|
if (had_error) return;
|
||||||
|
|
||||||
|
/* Calculate the segment and offset. */
|
||||||
|
seg = load_adr.pc_addr >> BC_SEG_LOG;
|
||||||
|
offset = load_adr.pc_addr++ % BC_SEG_SIZE;
|
||||||
|
func = load_adr.pc_func;
|
||||||
|
|
||||||
|
if (seg >= BC_MAX_SEGS)
|
||||||
|
{
|
||||||
|
yyerror ("Function too big.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functions[func].f_body[seg] == NULL)
|
||||||
|
functions[func].f_body[seg] = (char *) bc_malloc (BC_SEG_SIZE);
|
||||||
|
|
||||||
|
/* Store the byte. */
|
||||||
|
functions[func].f_body[seg][offset] = byte;
|
||||||
|
functions[func].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(**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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
323
contrib/bc/bc/main.c
Normal file
323
contrib/bc/bc/main.c
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
/* main.c: The main program 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
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
#include "bcdefs.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include "global.h"
|
||||||
|
#include "proto.h"
|
||||||
|
#include "getopt.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables for processing multiple files. */
|
||||||
|
char first_file;
|
||||||
|
extern FILE *yyin;
|
||||||
|
|
||||||
|
/* Points to the last node in the file name list for easy adding. */
|
||||||
|
static file_node *last = NULL;
|
||||||
|
|
||||||
|
#ifdef READLINE
|
||||||
|
/* Readline support. */
|
||||||
|
extern char *rl_readline_name;
|
||||||
|
extern FILE *rl_instream;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* long option support */
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{"compile", 0, &compile_only, TRUE},
|
||||||
|
{"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
|
||||||
|
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, "lciqsvw", long_options, &long_index);
|
||||||
|
|
||||||
|
if (optch == EOF) /* End of arguments. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (optch)
|
||||||
|
{
|
||||||
|
case 'c': /* compile only */
|
||||||
|
compile_only = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l': /* math lib */
|
||||||
|
use_math = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i': /* force interactive */
|
||||||
|
interactive = 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. */
|
||||||
|
printf ("%s\n", BC_VERSION);
|
||||||
|
exit (0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w': /* Non standard features give warnings. */
|
||||||
|
warn_not_std = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
#ifdef READLINE
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
#ifdef BC_MATH_FILE
|
||||||
|
/* Make the first file be the math library. */
|
||||||
|
new_file = fopen (BC_MATH_FILE, "r");
|
||||||
|
use_math = FALSE;
|
||||||
|
if (new_file != NULL)
|
||||||
|
{
|
||||||
|
new_yy_file (new_file);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf (stderr, "Math Library unavailable.\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Load the code from a precompiled version of the math libarary. */
|
||||||
|
extern char libmath[];
|
||||||
|
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);
|
||||||
|
load_code (libmath);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
446
contrib/bc/bc/sbc.y
Normal file
446
contrib/bc/bc/sbc.y
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
%{
|
||||||
|
/* 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, 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 "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> NEWLINE 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 NEWLINE
|
||||||
|
{ run_code(); }
|
||||||
|
| function
|
||||||
|
{ run_code(); }
|
||||||
|
| error NEWLINE
|
||||||
|
{
|
||||||
|
yyerrok;
|
||||||
|
init_gen() ;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
semicolon_list : /* empty */
|
||||||
|
{ $$ = 0; }
|
||||||
|
| statement_or_error
|
||||||
|
| semicolon_list ';' statement_or_error
|
||||||
|
| semicolon_list ';'
|
||||||
|
;
|
||||||
|
statement_list : /* empty */
|
||||||
|
{ $$ = 0; }
|
||||||
|
| statement
|
||||||
|
| statement_list NEWLINE
|
||||||
|
| statement_list NEWLINE 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 ')' '{'
|
||||||
|
NEWLINE 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 NEWLINE '}'
|
||||||
|
{
|
||||||
|
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 NEWLINE
|
||||||
|
{ $$ = $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; }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
1612
contrib/bc/bc/scan.c
Normal file
1612
contrib/bc/bc/scan.c
Normal file
File diff suppressed because it is too large
Load Diff
293
contrib/bc/bc/scan.l
Normal file
293
contrib/bc/bc/scan.l
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
%{
|
||||||
|
/* 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, 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 "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));
|
||||||
|
|
||||||
|
#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 char rl_len = 0;
|
||||||
|
|
||||||
|
/* Definitions for readline access. */
|
||||||
|
extern FILE *rl_instream;
|
||||||
|
_PROTOTYPE(char *readline, (char *));
|
||||||
|
|
||||||
|
/* Needed here? */
|
||||||
|
extern FILE *yyin;
|
||||||
|
|
||||||
|
/* 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_line)
|
||||||
|
free(rl_line);
|
||||||
|
rl_line = readline ("");
|
||||||
|
if (rl_line == NULL) {
|
||||||
|
/* end of file */
|
||||||
|
*result = 0;
|
||||||
|
rl_len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rl_len = strlen (rl_line)+1;
|
||||||
|
if (rl_len != 1)
|
||||||
|
add_history (rl_line);
|
||||||
|
rl_line[rl_len-1] = '\n';
|
||||||
|
printf ("\r");
|
||||||
|
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_len -= max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* 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(NEWLINE); }
|
||||||
|
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 {
|
||||||
|
#ifdef READLINE
|
||||||
|
return(History);
|
||||||
|
#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(NEWLINE); }
|
||||||
|
\\\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: \\%3d", (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. */
|
||||||
|
}
|
1070
contrib/bc/bc/storage.c
Normal file
1070
contrib/bc/bc/storage.c
Normal file
File diff suppressed because it is too large
Load Diff
859
contrib/bc/bc/util.c
Normal file
859
contrib/bc/bc/util.c
Normal file
@ -0,0 +1,859 @@
|
|||||||
|
/* util.c: Utility routines 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
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#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)
|
||||||
|
char 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)
|
||||||
|
char 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 warranty information. */
|
||||||
|
|
||||||
|
void
|
||||||
|
warranty(prefix)
|
||||||
|
char *prefix;
|
||||||
|
{
|
||||||
|
printf ("\n%s%s\n\n", prefix, BC_VERSION);
|
||||||
|
printf ("%s%s%s%s%s%s%s%s%s%s%s",
|
||||||
|
" 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 the Free Software\n",
|
||||||
|
" Foundation, 675 Mass Ave, Cambridge, MA 02139, 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 ("MAX code = %ld\n", (long) BC_MAX_SEGS * (long) BC_SEG_SIZE);
|
||||||
|
printf ("multiply digits = %ld\n", (long) LONG_MAX / (long) 90);
|
||||||
|
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;
|
||||||
|
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 (func=%s, adr=%d): %s\n",
|
||||||
|
f_names[pc.pc_func], pc.pc_addr, error_mesg);
|
||||||
|
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;
|
||||||
|
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 (func=%s, adr=%d): %s\n",
|
||||||
|
f_names[pc.pc_func], pc.pc_addr, error_mesg);
|
||||||
|
}
|
68
contrib/bc/config.h.in
Normal file
68
contrib/bc/config.h.in
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
|
/* PACKAGE name */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Package VERSION number */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* define if the math lib is to be loaded from a file. */
|
||||||
|
#undef BC_MATH_FILE
|
||||||
|
|
||||||
|
/* Define to use the readline library. */
|
||||||
|
#undef READLINE
|
||||||
|
|
||||||
|
/* 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 <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
|
2315
contrib/bc/configure
vendored
Executable file
2315
contrib/bc/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
69
contrib/bc/configure.in
Normal file
69
contrib/bc/configure.in
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
AC_INIT(doc/bc.1)
|
||||||
|
AM_INIT_AUTOMAKE(bc, 1.04)
|
||||||
|
AM_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_MINIX
|
||||||
|
dnl AC_ISC_POSIX
|
||||||
|
|
||||||
|
AC_PROG_YACC
|
||||||
|
AC_DECL_YYTEXT
|
||||||
|
AC_PROG_LEX
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_WITH(readline,[ --with-readline support fancy command input editing], [
|
||||||
|
if test "$with_readline" = "yes" ; then
|
||||||
|
echo Using the readline library.
|
||||||
|
AC_DEFINE(READLINE,1)
|
||||||
|
LIBS="$LIBS -lreadline -ltermcap"
|
||||||
|
bcrl=y
|
||||||
|
else
|
||||||
|
bcrl=n
|
||||||
|
fi
|
||||||
|
], [
|
||||||
|
bcrl=n
|
||||||
|
])
|
||||||
|
|
||||||
|
if test "$LEX" = "flex" ; then
|
||||||
|
LEX="flex -I8"
|
||||||
|
else
|
||||||
|
if test "$bcrl" = "y" ; then
|
||||||
|
AC_MSG_WARN(readline works only with flex.)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
SaveCFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="-g -O -I. -I$srcdir"
|
||||||
|
AC_MSG_CHECKING(if long strings are accepted by the C compiler)
|
||||||
|
AC_TRY_COMPILE([
|
||||||
|
char libmath[] =
|
||||||
|
#include "bc/libmath.h"
|
||||||
|
;
|
||||||
|
],[],AC_MSG_RESULT(yes),
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_WARN(libmath.b will not be preloaded into the executable)
|
||||||
|
if test "${prefix}" = "NONE" ; then
|
||||||
|
AC_DEFINE_UNQUOTED(BC_MATH_FILE,"/usr/local/lib/libmath.b")
|
||||||
|
else
|
||||||
|
AC_DEFINE_UNQUOTED(BC_MATH_FILE,"${prefix}/lib/libmath.b")
|
||||||
|
fi)
|
||||||
|
CFLAGS="$SaveCFLAGS"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_PROGRAM
|
||||||
|
AC_OUTPUT(Makefile bc/Makefile dc/Makefile doc/Makefile lib/Makefile)
|
10
contrib/bc/dc/Makefile.am
Normal file
10
contrib/bc/dc/Makefile.am
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## 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
|
||||||
|
|
||||||
|
$(PROGRAMS): $(LDADD)
|
250
contrib/bc/dc/Makefile.in
Normal file
250
contrib/bc/dc/Makefile.in
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
# Makefile.in generated automatically by automake 1.1n from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
transform = @program_transform_name@
|
||||||
|
|
||||||
|
NORMAL_INSTALL = true
|
||||||
|
PRE_INSTALL = true
|
||||||
|
POST_INSTALL = true
|
||||||
|
NORMAL_UNINSTALL = true
|
||||||
|
PRE_UNINSTALL = true
|
||||||
|
POST_UNINSTALL = true
|
||||||
|
CC = @CC@
|
||||||
|
LEX = @LEX@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
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
|
||||||
|
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 =
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||||
|
LINK = $(CC) $(LDFLAGS) -o $@
|
||||||
|
HEADERS = $(noinst_HEADERS)
|
||||||
|
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP = --best
|
||||||
|
SOURCES = $(dc_SOURCES)
|
||||||
|
OBJECTS = $(dc_OBJECTS)
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .c .o
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu dc/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
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) $(bindir)
|
||||||
|
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
if test -f $$p; then \
|
||||||
|
echo " $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed '$(transform)'`"; \
|
||||||
|
$(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed '$(transform)'`; \
|
||||||
|
else :; fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-binPROGRAMS:
|
||||||
|
$(NORMAL_UNINSTALL)
|
||||||
|
list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
rm -f $(bindir)/`echo $$p|sed '$(transform)'`; \
|
||||||
|
done
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(COMPILE) -c $<
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
rm -f *.o 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)
|
||||||
|
here=`pwd` && cd $(srcdir) && mkid -f$$here/ID $(SOURCES) $(HEADERS)
|
||||||
|
|
||||||
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||||
|
done; \
|
||||||
|
test -z "$(ETAGS_ARGS)$(SOURCES)$(HEADERS)$$tags" \
|
||||||
|
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $(SOURCES) $(HEADERS) -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); \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||||
|
done
|
||||||
|
info:
|
||||||
|
dvi:
|
||||||
|
check: all
|
||||||
|
$(MAKE)
|
||||||
|
installcheck:
|
||||||
|
install-exec: install-binPROGRAMS
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install-data:
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install: install-exec install-data all
|
||||||
|
@:
|
||||||
|
|
||||||
|
uninstall: uninstall-binPROGRAMS
|
||||||
|
|
||||||
|
all: $(PROGRAMS) $(HEADERS) Makefile
|
||||||
|
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||||
|
installdirs:
|
||||||
|
$(mkinstalldirs) $(bindir)
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
rm -f Makefile $(DISTCLEANFILES)
|
||||||
|
rm -f config.cache config.log stamp-h
|
||||||
|
test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||||
|
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||||
|
mostlyclean: mostlyclean-binPROGRAMS mostlyclean-compile \
|
||||||
|
mostlyclean-tags mostlyclean-generic
|
||||||
|
|
||||||
|
clean: clean-binPROGRAMS clean-compile clean-tags clean-generic \
|
||||||
|
mostlyclean
|
||||||
|
|
||||||
|
distclean: distclean-binPROGRAMS distclean-compile distclean-tags \
|
||||||
|
distclean-generic clean
|
||||||
|
rm -f config.status
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-binPROGRAMS maintainer-clean-compile \
|
||||||
|
maintainer-clean-tags maintainer-clean-generic \
|
||||||
|
distclean
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
.PHONY: default 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 dvi installcheck \
|
||||||
|
install-exec install-data install uninstall 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:
|
108
contrib/bc/dc/array.c
Normal file
108
contrib/bc/dc/array.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* implement arrays for dc
|
||||||
|
*
|
||||||
|
* 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.; 675 Mass Ave. Cambridge, MA 02139, 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;
|
||||||
|
};
|
||||||
|
typedef struct dc_array dc_array;
|
||||||
|
|
||||||
|
/* I can find no reason not to place arrays in their own namespace... */
|
||||||
|
static dc_array *dc_array_register[DC_REGCOUNT];
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize the arrays to their initial values */
|
||||||
|
void
|
||||||
|
dc_array_init DC_DECLVOID()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<DC_REGCOUNT; ++i)
|
||||||
|
dc_array_register[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
{
|
||||||
|
dc_array *cur;
|
||||||
|
dc_array *prev=NULL;
|
||||||
|
dc_array *newentry;
|
||||||
|
|
||||||
|
array_id = regmap(array_id);
|
||||||
|
cur = dc_array_register[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_array_register[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
|
||||||
|
{
|
||||||
|
dc_array *cur;
|
||||||
|
|
||||||
|
for (cur=dc_array_register[regmap(array_id)]; cur; cur=cur->next)
|
||||||
|
if (cur->Index == Index)
|
||||||
|
return dc_dup(cur->value);
|
||||||
|
return dc_int2data(0);
|
||||||
|
}
|
83
contrib/bc/dc/dc-proto.h
Normal file
83
contrib/bc/dc/dc-proto.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* prototypes of all externally visible dc functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 void dc_array_set DC_PROTO((int, int, dc_data));
|
||||||
|
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_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_boolean, dc_boolean));
|
||||||
|
extern void dc_out_str DC_PROTO((dc_str, dc_boolean, dc_boolean));
|
||||||
|
extern void dc_print DC_PROTO((dc_data, int));
|
||||||
|
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_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_boolean));
|
||||||
|
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_boolean));
|
||||||
|
extern int dc_tell_scale DC_PROTO((dc_num, dc_boolean));
|
||||||
|
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 *));
|
40
contrib/bc/dc/dc-regdef.h
Normal file
40
contrib/bc/dc/dc-regdef.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.; 675 Mass Ave. Cambridge, MA 02139, 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
|
173
contrib/bc/dc/dc.c
Normal file
173
contrib/bc/dc/dc.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* implement the "dc" Desk Calculator language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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"
|
||||||
|
|
||||||
|
#include "version.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 */
|
||||||
|
|
||||||
|
/* 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\
|
||||||
|
Report bugs to @\n\
|
||||||
|
", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
show_version DC_DECLVOID()
|
||||||
|
{
|
||||||
|
printf("%s\n\n", DC_VERSION);
|
||||||
|
printf("Email bug reports to: bug-gnu-utils@prep.ai.mit.edu .\n");
|
||||||
|
printf("Be sure to include the word ``dc'' \
|
||||||
|
somewhere in the ``Subject:'' field.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 ( !(input=fopen(filename, "r")) ) {
|
||||||
|
fprintf(stderr, "Could not open file ");
|
||||||
|
perror(filename);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (dc_evalfile(input))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
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, '/');
|
||||||
|
dc_math_init();
|
||||||
|
dc_string_init();
|
||||||
|
dc_register_init();
|
||||||
|
dc_array_init();
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, "hVe:", 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) {
|
||||||
|
if (strcmp(argv[optind], "-") == 0) {
|
||||||
|
if (dc_evalfile(stdin))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
78
contrib/bc/dc/dc.h
Normal file
78
contrib/bc/dc/dc.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Header file for dc routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_FALSE, DC_TRUE} dc_boolean;
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 */
|
646
contrib/bc/dc/eval.c
Normal file
646
contrib/bc/dc/eval.c
Normal file
@ -0,0 +1,646 @@
|
|||||||
|
/*
|
||||||
|
* evaluate the dc language, from a FILE* or a string
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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_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_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
|
||||||
|
*/
|
||||||
|
static dc_status
|
||||||
|
dc_func DC_DECLARG((c, peekc))
|
||||||
|
int c DC_DECLSEP
|
||||||
|
int peekc 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 and exp must be a
|
||||||
|
* non-negative integer. 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)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
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 */
|
||||||
|
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_TRUE);
|
||||||
|
dc_free_num(&datum.v.number);
|
||||||
|
}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_TRUE);
|
||||||
|
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_TRUE);
|
||||||
|
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 '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_TRUE);
|
||||||
|
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 */
|
||||||
|
if (dc_top_of_stack(&datum) == DC_SUCCESS)
|
||||||
|
dc_print(datum, dc_obase);
|
||||||
|
break;
|
||||||
|
case 'q': /* quit two levels of evaluation, posibly exiting program */
|
||||||
|
unwind_depth = 2;
|
||||||
|
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': /* print the value popped off of top-of-stack;
|
||||||
|
* do not add a trailing newline
|
||||||
|
*/
|
||||||
|
if (dc_pop(&datum) == DC_SUCCESS){
|
||||||
|
if (datum.dc_type == DC_STRING)
|
||||||
|
dc_out_str(datum.v.string, DC_FALSE, DC_TRUE);
|
||||||
|
else if (datum.dc_type == DC_NUMBER)
|
||||||
|
dc_out_num(datum.v.number, dc_obase, DC_FALSE, DC_TRUE);
|
||||||
|
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_TRUE);
|
||||||
|
if (unwind_depth > 0)
|
||||||
|
return DC_QUIT;
|
||||||
|
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_TRUE);
|
||||||
|
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_TRUE);
|
||||||
|
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_TRUE)));
|
||||||
|
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_TRUE);
|
||||||
|
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_TRUE);
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
switch (dc_func(c, peekc)){
|
||||||
|
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_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;
|
||||||
|
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;
|
||||||
|
switch (dc_func(c, peekc)){
|
||||||
|
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_FAIL;
|
||||||
|
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_EOF_ERROR:
|
||||||
|
fprintf(stderr, "%s: unexpected EOF\n", progname);
|
||||||
|
return DC_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DC_SUCCESS;
|
||||||
|
}
|
177
contrib/bc/dc/misc.c
Normal file
177
contrib/bc/dc/misc.c
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* misc. functions for the "dc" Desk Calculator language.
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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"
|
||||||
|
|
||||||
|
#include "version.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))
|
||||||
|
dc_data value DC_DECLSEP
|
||||||
|
int obase DC_DECLEND
|
||||||
|
{
|
||||||
|
if (value.dc_type == DC_NUMBER) {
|
||||||
|
dc_out_num(value.v.number, obase, DC_TRUE, DC_FALSE);
|
||||||
|
} else if (value.dc_type == DC_STRING) {
|
||||||
|
dc_out_str(value.v.string, DC_TRUE, DC_FALSE);
|
||||||
|
} 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);
|
||||||
|
}
|
536
contrib/bc/dc/numeric.c
Normal file
536
contrib/bc/dc/numeric.c
Normal file
@ -0,0 +1,536 @@
|
|||||||
|
/*
|
||||||
|
* interface dc to the bc numeric routines
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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>
|
||||||
|
#include "bcdefs.h"
|
||||||
|
#include "proto.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "dc.h"
|
||||||
|
#include "dc-proto.h"
|
||||||
|
|
||||||
|
/* 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 DC_DECLSEP
|
||||||
|
dc_num *result DC_DECLEND
|
||||||
|
{
|
||||||
|
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 DC_DECLSEP
|
||||||
|
dc_num *result DC_DECLEND
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
init_num((bc_num *)quotient);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
init_num((bc_num *)result);
|
||||||
|
if (bc_raisemod(CastNum(base), CastNum(expo), CastNum(mod),
|
||||||
|
(bc_num *)result, kscale)){
|
||||||
|
if (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
|
||||||
|
{
|
||||||
|
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 = copy_num(CastNum(value));
|
||||||
|
if (!bc_sqrt(&tmp, kscale)){
|
||||||
|
fprintf(stderr, "%s: square root of negative number\n", progname);
|
||||||
|
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_flag is true then deallocate the value after use.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dc_num2int DC_DECLARG((value, discard_flag))
|
||||||
|
dc_num value DC_DECLSEP
|
||||||
|
dc_boolean discard_flag DC_DECLEND
|
||||||
|
{
|
||||||
|
long result;
|
||||||
|
|
||||||
|
result = num2long(CastNum(value));
|
||||||
|
if (discard_flag)
|
||||||
|
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;
|
||||||
|
|
||||||
|
init_num((bc_num *)&result.v.number);
|
||||||
|
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;
|
||||||
|
|
||||||
|
init_num(&tmp);
|
||||||
|
init_num(&build);
|
||||||
|
init_num(&base);
|
||||||
|
result = copy_num(_zero_);
|
||||||
|
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)();
|
||||||
|
int2num(&tmp, digit);
|
||||||
|
bc_multiply(result, base, &result, 0);
|
||||||
|
bc_add(result, tmp, &result, 0);
|
||||||
|
}
|
||||||
|
if (c == '.'){
|
||||||
|
free_num(&build);
|
||||||
|
free_num(&tmp);
|
||||||
|
divisor = copy_num(_one_);
|
||||||
|
build = 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;
|
||||||
|
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);
|
||||||
|
|
||||||
|
free_num(&tmp);
|
||||||
|
free_num(&build);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the scale factor of the passed dc_num
|
||||||
|
* If discard_flag is true then deallocate the value after use.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dc_tell_scale DC_DECLARG((value, discard_flag))
|
||||||
|
dc_num value DC_DECLSEP
|
||||||
|
dc_boolean discard_flag DC_DECLEND
|
||||||
|
{
|
||||||
|
int kscale;
|
||||||
|
|
||||||
|
kscale = CastNum(value)->n_scale;
|
||||||
|
if (discard_flag)
|
||||||
|
dc_free_num(&value);
|
||||||
|
return kscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* initialize the math subsystem */
|
||||||
|
void
|
||||||
|
dc_math_init DC_DECLVOID()
|
||||||
|
{
|
||||||
|
init_numbers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print out a dc_num in output base obase to stdout;
|
||||||
|
* if newline is true, terminate output with a '\n';
|
||||||
|
* if discard_flag is true then deallocate the value after use
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dc_out_num DC_DECLARG((value, obase, newline, discard_flag))
|
||||||
|
dc_num value DC_DECLSEP
|
||||||
|
int obase DC_DECLSEP
|
||||||
|
dc_boolean newline DC_DECLSEP
|
||||||
|
dc_boolean discard_flag DC_DECLEND
|
||||||
|
{
|
||||||
|
out_num(CastNum(value), obase, out_char);
|
||||||
|
if (newline)
|
||||||
|
out_char('\n');
|
||||||
|
if (discard_flag)
|
||||||
|
dc_free_num(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* deallocate an instance of a dc_num */
|
||||||
|
void
|
||||||
|
dc_free_num DC_DECLARG((value))
|
||||||
|
dc_num *value DC_DECLEND
|
||||||
|
{
|
||||||
|
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>". */
|
||||||
|
|
||||||
|
void
|
||||||
|
out_char (ch)
|
||||||
|
char ch;
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
out_col = 0;
|
||||||
|
putchar ('\n');
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
char error_mesg [255];
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
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. */
|
||||||
|
|
||||||
|
#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;
|
||||||
|
char error_mesg [255];
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
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);
|
||||||
|
}
|
457
contrib/bc/dc/stack.c
Normal file
457
contrib/bc/dc/stack.c
Normal file
@ -0,0 +1,457 @@
|
|||||||
|
/*
|
||||||
|
* implement stack functions for dc
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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_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->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);
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
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_flag is true, 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_flag))
|
||||||
|
dc_data value DC_DECLSEP
|
||||||
|
dc_boolean discard_flag DC_DECLEND
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
|
||||||
|
if (value.dc_type == DC_NUMBER){
|
||||||
|
length = dc_numlen(value.v.number);
|
||||||
|
if (discard_flag == DC_TRUE)
|
||||||
|
dc_free_num(&value.v.number);
|
||||||
|
} else if (value.dc_type == DC_STRING) {
|
||||||
|
length = dc_strlen(value.v.string);
|
||||||
|
if (discard_flag == DC_TRUE)
|
||||||
|
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);
|
||||||
|
}
|
208
contrib/bc/dc/string.c
Normal file
208
contrib/bc/dc/string.c
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* implement string functions for dc
|
||||||
|
*
|
||||||
|
* Copyright (C) 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 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_boolean newline DC_DECLSEP
|
||||||
|
dc_boolean discard_flag DC_DECLEND
|
||||||
|
{
|
||||||
|
fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
|
||||||
|
if (newline == DC_TRUE)
|
||||||
|
printf("\n");
|
||||||
|
if (discard_flag == DC_TRUE)
|
||||||
|
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 */
|
||||||
|
}
|
10
contrib/bc/doc/Makefile.am
Normal file
10
contrib/bc/doc/Makefile.am
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
info_TEXINFOS = dc.texi
|
||||||
|
MAKEINFO = makeinfo --no-split
|
||||||
|
|
||||||
|
# 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
|
280
contrib/bc/doc/Makefile.in
Normal file
280
contrib/bc/doc/Makefile.in
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
# Makefile.in generated automatically by automake 1.1n from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
transform = @program_transform_name@
|
||||||
|
|
||||||
|
NORMAL_INSTALL = true
|
||||||
|
PRE_INSTALL = true
|
||||||
|
POST_INSTALL = true
|
||||||
|
NORMAL_UNINSTALL = true
|
||||||
|
PRE_UNINSTALL = true
|
||||||
|
POST_UNINSTALL = true
|
||||||
|
CC = @CC@
|
||||||
|
LEX = @LEX@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
YACC = @YACC@
|
||||||
|
|
||||||
|
info_TEXINFOS = dc.texi
|
||||||
|
MAKEINFO = makeinfo --no-split
|
||||||
|
|
||||||
|
# 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
|
||||||
|
TEXINFO_TEX = $(srcdir)/texinfo.tex
|
||||||
|
INFO_DEPS = dc.info
|
||||||
|
DVIS = dc.dvi
|
||||||
|
TEXINFOS = dc.texi
|
||||||
|
MANS = bc.1 dc.1
|
||||||
|
|
||||||
|
NROFF = nroff
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in texinfo.tex
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP = --best
|
||||||
|
default: all
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .texi .texinfo .info .dvi .ps
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
cd $(top_builddir) \
|
||||||
|
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||||
|
|
||||||
|
|
||||||
|
dc.info: dc.texi
|
||||||
|
dc.dvi: dc.texi
|
||||||
|
|
||||||
|
|
||||||
|
DVIPS = dvips
|
||||||
|
|
||||||
|
.texi.info:
|
||||||
|
cd $(srcdir) \
|
||||||
|
&& $(MAKEINFO) `echo $< | sed 's,.*/,,'`
|
||||||
|
|
||||||
|
.texi.dvi:
|
||||||
|
TEXINPUTS=$(srcdir):$$TEXINPUTS \
|
||||||
|
MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
|
||||||
|
|
||||||
|
.texi:
|
||||||
|
cd $(srcdir) \
|
||||||
|
&& $(MAKEINFO) `echo $< | sed 's,.*/,,'`
|
||||||
|
|
||||||
|
.texinfo.info:
|
||||||
|
cd $(srcdir) \
|
||||||
|
&& $(MAKEINFO) `echo $< | sed 's,.*/,,'`
|
||||||
|
|
||||||
|
.texinfo:
|
||||||
|
cd $(srcdir) \
|
||||||
|
&& $(MAKEINFO) `echo $< | sed 's,.*/,,'`
|
||||||
|
|
||||||
|
.texinfo.dvi:
|
||||||
|
TEXINPUTS=$(srcdir):$$TEXINPUTS \
|
||||||
|
MAKEINFO='$(MAKEINFO) -I $(srcdir)' $(TEXI2DVI) $<
|
||||||
|
.dvi.ps:
|
||||||
|
$(DVIPS) $< -o $@
|
||||||
|
|
||||||
|
install-info-am: $(INFO_DEPS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
$(mkinstalldirs) $(infodir)
|
||||||
|
@for file in $(INFO_DEPS); 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 $(infodir)/$$ifile"; \
|
||||||
|
$(INSTALL_DATA) $$d/$$ifile $(infodir)/$$ifile; \
|
||||||
|
else : ; fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
@$(POST_INSTALL)
|
||||||
|
@if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
|
||||||
|
for file in $(INFO_DEPS); do \
|
||||||
|
echo " install-info --info-dir=$(infodir) $(infodir)/$$file";\
|
||||||
|
install-info --info-dir=$(infodir) $(infodir)/$$file; :;\
|
||||||
|
done; \
|
||||||
|
else : ; fi
|
||||||
|
|
||||||
|
uninstall-info:
|
||||||
|
$(PRE_UNINSTALL)
|
||||||
|
if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
|
||||||
|
ii=yes; \
|
||||||
|
else ii=; fi; \
|
||||||
|
for file in $(INFO_DEPS); do \
|
||||||
|
test -z $ii || install-info --info-dir=$(infodir) --remove $$file; \
|
||||||
|
done
|
||||||
|
$(NORMAL_UNINSTALL)
|
||||||
|
for file in $(INFO_DEPS); do \
|
||||||
|
(cd $(infodir) && rm -f $$file $$file-[0-9] $$file-[0-9][0-9]); \
|
||||||
|
done
|
||||||
|
|
||||||
|
dist-info: $(INFO_DEPS)
|
||||||
|
for base in $(INFO_DEPS); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
for file in `cd $$d && eval echo $$base*`; do \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
mostlyclean-info:
|
||||||
|
rm -f dc.aux dc.cp dc.cps dc.dvi dc.fn dc.fns dc.ky dc.log dc.pg dc.toc \
|
||||||
|
dc.tp dc.tps dc.vr dc.vrs dc.op dc.tr dc.cv
|
||||||
|
|
||||||
|
clean-info:
|
||||||
|
|
||||||
|
distclean-info:
|
||||||
|
|
||||||
|
maintainer-clean-info:
|
||||||
|
for i in $(INFO_DEPS); do rm -f `eval echo $$i*`; done
|
||||||
|
install-man: $(MANS)
|
||||||
|
$(NORMAL_INSTALL)
|
||||||
|
$(mkinstalldirs) $(mandir)/man1
|
||||||
|
@sect=1; \
|
||||||
|
inst=`echo "bc" | sed '$(transform)'`.1; \
|
||||||
|
if test -f $(srcdir)/bc.1; then file=$(srcdir)/bc.1; \
|
||||||
|
else file=bc.1; fi; \
|
||||||
|
echo " $(INSTALL_DATA) $$file $(mandir)/man$$sect/$$inst"; \
|
||||||
|
$(INSTALL_DATA) $$file $(mandir)/man$$sect/$$inst
|
||||||
|
@sect=1; \
|
||||||
|
inst=`echo "dc" | sed '$(transform)'`.1; \
|
||||||
|
if test -f $(srcdir)/dc.1; then file=$(srcdir)/dc.1; \
|
||||||
|
else file=dc.1; fi; \
|
||||||
|
echo " $(INSTALL_DATA) $$file $(mandir)/man$$sect/$$inst"; \
|
||||||
|
$(INSTALL_DATA) $$file $(mandir)/man$$sect/$$inst
|
||||||
|
|
||||||
|
uninstall-man:
|
||||||
|
$(NORMAL_UNINSTALL)
|
||||||
|
inst=`echo "bc" | sed '$(transform)'`.1; \
|
||||||
|
rm -f $(mandir)/man1/$$inst
|
||||||
|
inst=`echo "dc" | sed '$(transform)'`.1; \
|
||||||
|
rm -f $(mandir)/man1/$$inst
|
||||||
|
|
||||||
|
tags: TAGS
|
||||||
|
TAGS:
|
||||||
|
|
||||||
|
|
||||||
|
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||||
|
|
||||||
|
subdir = doc
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@for file in $(DISTFILES); do \
|
||||||
|
d=$(srcdir); \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||||
|
done
|
||||||
|
$(MAKE) distdir="$(distdir)" dist-info
|
||||||
|
info: $(INFO_DEPS)
|
||||||
|
dvi: $(DVIS)
|
||||||
|
check: all
|
||||||
|
$(MAKE)
|
||||||
|
installcheck:
|
||||||
|
install-exec:
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install-data: install-info-am install-man
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install: install-exec install-data all
|
||||||
|
@:
|
||||||
|
|
||||||
|
uninstall: uninstall-info uninstall-man
|
||||||
|
|
||||||
|
all: $(INFO_DEPS) $(MANS) Makefile
|
||||||
|
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||||
|
installdirs:
|
||||||
|
$(mkinstalldirs) $(infodir) $(mandir)/man1
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
rm -f Makefile $(DISTCLEANFILES)
|
||||||
|
rm -f config.cache config.log stamp-h
|
||||||
|
test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||||
|
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||||
|
mostlyclean: mostlyclean-info mostlyclean-generic
|
||||||
|
|
||||||
|
clean: clean-info clean-generic mostlyclean
|
||||||
|
|
||||||
|
distclean: distclean-info distclean-generic clean
|
||||||
|
rm -f config.status
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-info maintainer-clean-generic \
|
||||||
|
distclean
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
.PHONY: default install-info-am uninstall-info mostlyclean-info \
|
||||||
|
distclean-info clean-info maintainer-clean-info install-man \
|
||||||
|
uninstall-man tags distdir info dvi installcheck install-exec \
|
||||||
|
install-data install uninstall 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:
|
787
contrib/bc/doc/bc.1
Normal file
787
contrib/bc/doc/bc.1
Normal file
@ -0,0 +1,787 @@
|
|||||||
|
.\"
|
||||||
|
.\" bc.1 - the *roff document processor source for the bc manual
|
||||||
|
.\"
|
||||||
|
.\" 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
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.TH bc 1 .\" "Command Manual" v1.04 "June 22, 1995"
|
||||||
|
.SH NAME
|
||||||
|
bc - An arbitrary precision calculator language
|
||||||
|
.SH SYNTAX
|
||||||
|
\fBbc\fR [ \fB-lwsqv\fR ] [long-options] [ \fI file ...\fR ]
|
||||||
|
.SH VERSION
|
||||||
|
This man page documents GNU bc version 1.04.
|
||||||
|
.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 -l
|
||||||
|
Define the standard math library.
|
||||||
|
.IP -w
|
||||||
|
Give warnings for extensions to POSIX \fBbc\fR.
|
||||||
|
.IP -s
|
||||||
|
Process exactly the POSIX \fBbc\fR language.
|
||||||
|
.IP -q
|
||||||
|
Do not print the normal GNU bc welcome.
|
||||||
|
.IP -v
|
||||||
|
Print the version number and copyright and quit.
|
||||||
|
.IP --mathlib
|
||||||
|
Define the standard math library.
|
||||||
|
.IP --warn
|
||||||
|
Give warnings for extensions to POSIX \fBbc\fR.
|
||||||
|
.IP --standard
|
||||||
|
Process exactly the POSIX \fBbc\fR language.
|
||||||
|
.IP --quiet
|
||||||
|
Do not print the normal GNU bc welcome.
|
||||||
|
.IP --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 cause the side effect of assigning the printed value the 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 the 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.)
|
||||||
|
.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
|
||||||
|
in the fact that 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.
|
||||||
|
.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 OPTION
|
||||||
|
GNU \fBbc\fR can be compiled (via a configure option) to use the
|
||||||
|
GNU \fBreadline\fR input editor library. This allows the user
|
||||||
|
to do more 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. A value of -1 means that an unlimited number
|
||||||
|
of history lines are retained. This is the default value.
|
||||||
|
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. For more information, read the
|
||||||
|
user manuals for the GNU \fBreadline\fR and \fBhistory\fR libraries.
|
||||||
|
.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 "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 "=+, =-, =*, =/, =%, =^"
|
||||||
|
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 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.
|
||||||
|
.IP "code size"
|
||||||
|
Each function and the "main" program are limited to 16384 bytes of
|
||||||
|
compiled byte code each. This limit (BC_MAX_SEGS) can be easily changed
|
||||||
|
to have more than 16 segments of 1024 bytes.
|
||||||
|
.IP "variable names"
|
||||||
|
The current limit on the number of unique names is 32767 for each of
|
||||||
|
simple variables, arrays and functions.
|
||||||
|
.SH ENVIRONMENT VARIABLES
|
||||||
|
The following environment variables are processed by \fBbc\fR:
|
||||||
|
.IP "POSIXLY_CORRECT"
|
||||||
|
This is the same as the \fB-s\fR option.
|
||||||
|
.IP "BC_ENV_ARGS"
|
||||||
|
This is another mechanism to get arguments to \fBbc\fR. The
|
||||||
|
format is the same as the command line arguments. These arguments
|
||||||
|
are processed first, so any files listed in the environent arguments
|
||||||
|
are processed before any command line argument files. This allows
|
||||||
|
the user to set up "standard" options and files to be processed
|
||||||
|
at every invocation of \fBbc\fR. The files in the environment
|
||||||
|
variables would typically contain function definitions for functions
|
||||||
|
the user wants defined every time \fBbc\fR is run.
|
||||||
|
.IP "BC_LINE_LENGTH"
|
||||||
|
This should be an integer specifing the number of characters in an
|
||||||
|
output line for numbers. This includes the backslash and newline characters
|
||||||
|
for long numbers.
|
||||||
|
.SH FILES
|
||||||
|
In most installations, \fBbc\fR is completely self-contained.
|
||||||
|
Where executable size is of importance or the C compiler does
|
||||||
|
not deal with very long strings, \fBbc\fR will read
|
||||||
|
the standard math library from the file /usr/local/lib/libmath.b.
|
||||||
|
(The actual location may vary. It may be /lib/libmath.b.)
|
||||||
|
.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-gnu-utils@prep.ai.mit.edu .
|
||||||
|
Be sure to include the word ``bc'' somewhere in the ``Subject:'' field.
|
||||||
|
.SH AUTHOR
|
||||||
|
.nf
|
||||||
|
Philip A. Nelson
|
||||||
|
phil@cs.wwu.edu
|
||||||
|
.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.
|
436
contrib/bc/doc/dc.1
Normal file
436
contrib/bc/doc/dc.1
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
.\"
|
||||||
|
.\" dc.1 - the *roff document processor source for the dc manual
|
||||||
|
.\"
|
||||||
|
.\" This file is part of GNU dc.
|
||||||
|
.\" Copyright (C) 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.
|
||||||
|
.\"
|
||||||
|
.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
|
||||||
|
.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.
|
||||||
|
.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 P
|
||||||
|
Prints the value on the top of the stack, popping it off,
|
||||||
|
and does not print a newline after.
|
||||||
|
.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 is controlled
|
||||||
|
by the current precision value (see below) and does not
|
||||||
|
depend on the values being multiplied.
|
||||||
|
.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 division is done with as many fraction digits
|
||||||
|
as the precision value specifies,
|
||||||
|
and the remainder is also computed with that many fraction digits.
|
||||||
|
.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.
|
||||||
|
The precision value specifies the number of fraction
|
||||||
|
digits in the result.
|
||||||
|
For small numbers this is like the sequence \fBSm lble^ Lm%\fP,
|
||||||
|
but, unlike \fB^\fP, this command will work with arbritrarily 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.
|
||||||
|
.PP
|
||||||
|
The remainder operation
|
||||||
|
.B %
|
||||||
|
requires some explanation:
|
||||||
|
applied to arguments ``a'' and ``b'' it produces ``a - (b * (a / b))'',
|
||||||
|
where ``a / b'' is computed in the current precision.
|
||||||
|
.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 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 36 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 less.
|
||||||
|
.TP
|
||||||
|
.BI = r
|
||||||
|
Similar but invokes the macro if the two numbers popped are 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.
|
||||||
|
.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.
|
||||||
|
.SH
|
||||||
|
NOTES
|
||||||
|
.PP
|
||||||
|
The array operations
|
||||||
|
.B :
|
||||||
|
and
|
||||||
|
.B ;
|
||||||
|
are usually only used by traditional implementations of
|
||||||
|
.IR bc .
|
||||||
|
(The GNU
|
||||||
|
.I bc
|
||||||
|
is self contained and does not need \*(dc to run.)
|
||||||
|
.SH
|
||||||
|
BUGS
|
||||||
|
.PP
|
||||||
|
Email bug reports to
|
||||||
|
.BR bug-gnu-utils@prep.ai.mit.edu .
|
||||||
|
Be sure to include the word ``dc'' somewhere in the ``Subject:'' field.
|
497
contrib/bc/doc/dc.texi
Normal file
497
contrib/bc/doc/dc.texi
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
\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
|
||||||
|
This file documents @sc{dc}, an arbitrary precision calculator.
|
||||||
|
|
||||||
|
Published by the Free Software Foundation,
|
||||||
|
675 Massachusetts Avenue,
|
||||||
|
Cambridge, MA 02139 USA
|
||||||
|
|
||||||
|
Copyright (C) 1984 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 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
@sp 2
|
||||||
|
Published by the Free Software Foundation, @*
|
||||||
|
675 Massachusetts Avenue, @*
|
||||||
|
Cambridge, MA 02139 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
|
||||||
|
* Notes:: Notes
|
||||||
|
@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 P
|
||||||
|
Prints the value on the top of the stack, popping it off,
|
||||||
|
and does not print a newline after.
|
||||||
|
|
||||||
|
@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 controlled
|
||||||
|
by the current precision value (see below) and does not
|
||||||
|
depend on the values being multiplied.
|
||||||
|
|
||||||
|
@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 division is done with as many fraction digits
|
||||||
|
as the precision value specifies,
|
||||||
|
and the remainder is also computed with that many fraction digits.
|
||||||
|
|
||||||
|
@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.
|
||||||
|
The precision value specifies the number of fraction
|
||||||
|
digits in the result.
|
||||||
|
For small numbers this is like the sequence @code{Sm lble^ Lm%},
|
||||||
|
but, unlike @code{^}, this command will work with arbritrarily large exponents.
|
||||||
|
|
||||||
|
@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.
|
||||||
|
|
||||||
|
The remainder operation (@samp{%}) requires some explanation:
|
||||||
|
applied to arguments @samp{a} and @samp{b}
|
||||||
|
it produces @samp{a - (b * (a / b))},
|
||||||
|
where @samp{a / b} is computed in the current precision.
|
||||||
|
|
||||||
|
@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 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 36 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 less.
|
||||||
|
|
||||||
|
@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 ?
|
||||||
|
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, Notes, Status Inquiry, Top
|
||||||
|
@chapter Miscellaneous
|
||||||
|
|
||||||
|
@table @samp
|
||||||
|
@item !
|
||||||
|
Will run the rest of the line as a system command.
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
@node Notes, , Miscellaneous, Top
|
||||||
|
@chapter Notes
|
||||||
|
|
||||||
|
The array operations @samp{:} and @samp{;} are usually
|
||||||
|
only used by traditional implementations of BC.
|
||||||
|
(The GNU implementation of BC is self contained
|
||||||
|
and does not need any version of @sc{dc} to run.)
|
||||||
|
|
||||||
|
Email bug reports to @code{bug-gnu-utils@@prep.ai.mit.edu}.
|
||||||
|
Be sure to include the word ``dc'' somewhere in the ``Subject:'' field.
|
||||||
|
|
||||||
|
@contents
|
||||||
|
@bye
|
4506
contrib/bc/doc/texinfo.tex
Normal file
4506
contrib/bc/doc/texinfo.tex
Normal file
File diff suppressed because it is too large
Load Diff
166
contrib/bc/h/bcdefs.h
Normal file
166
contrib/bc/h/bcdefs.h
Normal file
@ -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 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;
|
||||||
|
|
101
contrib/bc/h/const.h
Normal file
101
contrib/bc/h/const.h
Normal file
@ -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"
|
133
contrib/bc/h/getopt.h
Normal file
133
contrib/bc/h/getopt.h
Normal file
@ -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 */
|
147
contrib/bc/h/global.h
Normal file
147
contrib/bc/h/global.h
Normal file
@ -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;
|
||||||
|
|
65
contrib/bc/h/number.h
Normal file
65
contrib/bc/h/number.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* number.h: Arbitrary precision numbers header file. */
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {PLUS, MINUS} sign;
|
||||||
|
|
||||||
|
typedef 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. */
|
||||||
|
char n_value[1]; /* The storage. Not zero char terminated. It is
|
||||||
|
allocated with all other fields. */
|
||||||
|
} bc_struct;
|
||||||
|
|
||||||
|
typedef bc_struct *bc_num;
|
||||||
|
|
||||||
|
/* 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
|
171
contrib/bc/h/proto.h
Normal file
171
contrib/bc/h/proto.h
Normal file
@ -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
|
29
contrib/bc/h/version.h
Normal file
29
contrib/bc/h/version.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* version.h: version information for GNU bc and GNU dc */
|
||||||
|
|
||||||
|
/* This file is part of GNU bc and GNU dc.
|
||||||
|
* Copyright (C) 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, 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.04\nCopyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc."
|
||||||
|
|
||||||
|
#define DC_VERSION \
|
||||||
|
"dc 1.1 (GNU bc 1.04)\nCopyright (C) 1994, 1997 Free Software Foundation, Inc."
|
||||||
|
|
||||||
|
|
||||||
|
|
238
contrib/bc/install-sh
Executable file
238
contrib/bc/install-sh
Executable file
@ -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
|
9
contrib/bc/lib/Makefile.am
Normal file
9
contrib/bc/lib/Makefile.am
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
noinst_LIBRARIES = libbc.a
|
||||||
|
|
||||||
|
INCLUDES = -I$(srcdir) -I$(srcdir)/../h
|
||||||
|
|
||||||
|
libbc_a_SOURCES = getopt.c getopt1.c vfprintf.c number.c
|
||||||
|
|
||||||
|
#libbc_LIBADD = @LIBOBJS@
|
||||||
|
#libbc_DEPENDENCIES = $(bc_LIBADD)
|
230
contrib/bc/lib/Makefile.in
Normal file
230
contrib/bc/lib/Makefile.in
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
# Makefile.in generated automatically by automake 1.1n from Makefile.am
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
transform = @program_transform_name@
|
||||||
|
|
||||||
|
NORMAL_INSTALL = true
|
||||||
|
PRE_INSTALL = true
|
||||||
|
POST_INSTALL = true
|
||||||
|
NORMAL_UNINSTALL = true
|
||||||
|
PRE_UNINSTALL = true
|
||||||
|
POST_UNINSTALL = true
|
||||||
|
CC = @CC@
|
||||||
|
LEX = @LEX@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
YACC = @YACC@
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libbc.a
|
||||||
|
|
||||||
|
INCLUDES = -I$(srcdir) -I$(srcdir)/../h
|
||||||
|
|
||||||
|
libbc_a_SOURCES = getopt.c getopt1.c vfprintf.c number.c
|
||||||
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
|
CONFIG_HEADER = ../config.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
LIBRARIES = $(noinst_LIBRARIES)
|
||||||
|
|
||||||
|
|
||||||
|
DEFS = @DEFS@ -I. -I$(srcdir) -I..
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
libbc_a_LIBADD =
|
||||||
|
libbc_a_OBJECTS = getopt.o getopt1.o vfprintf.o number.o
|
||||||
|
AR = ar
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||||
|
LINK = $(CC) $(LDFLAGS) -o $@
|
||||||
|
DIST_COMMON = Makefile.am Makefile.in
|
||||||
|
|
||||||
|
|
||||||
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
|
TAR = tar
|
||||||
|
GZIP = --best
|
||||||
|
SOURCES = $(libbc_a_SOURCES)
|
||||||
|
OBJECTS = $(libbc_a_OBJECTS)
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .c .o
|
||||||
|
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||||
|
cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile
|
||||||
|
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||||
|
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 $<
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
rm -f *.o 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)
|
||||||
|
here=`pwd` && cd $(srcdir) && mkid -f$$here/ID $(SOURCES) $(HEADERS)
|
||||||
|
|
||||||
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||||
|
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||||
|
done; \
|
||||||
|
test -z "$(ETAGS_ARGS)$(SOURCES)$(HEADERS)$$tags" \
|
||||||
|
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $(SOURCES) $(HEADERS) -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); \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||||
|
done
|
||||||
|
info:
|
||||||
|
dvi:
|
||||||
|
check: all
|
||||||
|
$(MAKE)
|
||||||
|
installcheck:
|
||||||
|
install-exec:
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install-data:
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
|
||||||
|
install: install-exec install-data all
|
||||||
|
@:
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
|
||||||
|
all: $(LIBRARIES) Makefile
|
||||||
|
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
|
||||||
|
installdirs:
|
||||||
|
|
||||||
|
|
||||||
|
mostlyclean-generic:
|
||||||
|
test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
rm -f Makefile $(DISTCLEANFILES)
|
||||||
|
rm -f config.cache config.log stamp-h
|
||||||
|
test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||||
|
test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||||
|
mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
|
||||||
|
mostlyclean-tags mostlyclean-generic
|
||||||
|
|
||||||
|
clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
|
||||||
|
mostlyclean
|
||||||
|
|
||||||
|
distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
|
||||||
|
distclean-generic clean
|
||||||
|
rm -f config.status
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-noinstLIBRARIES \
|
||||||
|
maintainer-clean-compile maintainer-clean-tags \
|
||||||
|
maintainer-clean-generic distclean
|
||||||
|
@echo "This command is intended for maintainers to use;"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
|
||||||
|
.PHONY: default 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 dvi installcheck \
|
||||||
|
install-exec install-data install uninstall all installdirs \
|
||||||
|
mostlyclean-generic distclean-generic clean-generic \
|
||||||
|
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||||
|
|
||||||
|
|
||||||
|
#libbc_LIBADD = @LIBOBJS@
|
||||||
|
#libbc_DEPENDENCIES = $(bc_LIBADD)
|
||||||
|
|
||||||
|
# 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:
|
752
contrib/bc/lib/getopt.c
Normal file
752
contrib/bc/lib/getopt.c
Normal file
@ -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 */
|
184
contrib/bc/lib/getopt1.c
Normal file
184
contrib/bc/lib/getopt1.c
Normal file
@ -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 */
|
1565
contrib/bc/lib/number.c
Normal file
1565
contrib/bc/lib/number.c
Normal file
File diff suppressed because it is too large
Load Diff
31
contrib/bc/lib/vfprintf.c
Normal file
31
contrib/bc/lib/vfprintf.c
Normal file
@ -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 */
|
134
contrib/bc/missing
Executable file
134
contrib/bc/missing
Executable file
@ -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
|
36
contrib/bc/mkinstalldirs
Executable file
36
contrib/bc/mkinstalldirs
Executable file
@ -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
|
1
contrib/bc/stamp-h.in
Normal file
1
contrib/bc/stamp-h.in
Normal file
@ -0,0 +1 @@
|
|||||||
|
timestamp
|
Loading…
Reference in New Issue
Block a user