mirror of https://gitee.com/openkylin/bc.git
Import Upstream version 1.07.1
This commit is contained in:
commit
91a42210de
|
@ -0,0 +1,6 @@
|
|||
Phil Nelson <philnelson@acm.org> wrote bc, including the number.c
|
||||
source in the "lib" directory.
|
||||
|
||||
Ken Pizzini <ken@gnu.org> wrote dc, making use of the lib/number.c
|
||||
code that Phil Nelson wrote to handle the actual multiprecision
|
||||
arithmetic.
|
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. 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
|
||||
them 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 prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. 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.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey 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;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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 that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
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.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
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.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program 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, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
|
@ -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
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
Because of frequent questions ....... here is the BC FAQ
|
||||
|
||||
|
||||
1) Why does BC have its own arbitrary precision number routines
|
||||
(found in lib/number.c) rather than using GMP?
|
||||
|
||||
GMP has "integers" (no digits after a decimal), "rational numbers"
|
||||
(stored as 2 integers) and "floats". None of these will correctly
|
||||
represent a POSIX BC number. Floats are the closest, but will not
|
||||
behave correctly for many computations. For example, BC numbers have
|
||||
a "scale" that represent the number of digits to represent after the
|
||||
decimal point. The multiplying two of these numbers requires one to
|
||||
calculate an exact number of digits after the decimal point regardless
|
||||
of the number of digits in the integer part. GMP floats have a
|
||||
"fixed, but arbitrary" mantissa and so multiplying two floats will end
|
||||
up dropping digits BC must calculate.
|
||||
|
||||
2) The code "ibase=16; obase=10; FF" outputs FF, not 255. Isn't this
|
||||
a bug?
|
||||
|
||||
No. ibase changed the input base at that point. The 10 is then in
|
||||
base 16 and thus is the value 16. Therefore, both ibase and obase
|
||||
are 16 (decimal). And FF (base 16) on input is printed as FF (base 16)
|
||||
on output. So how can one get 255? First, single digit numbers are
|
||||
not converted using ibase. So A is always 10 (decimal). The following
|
||||
code will always work. "ibase=F+1; obase=A; FF" and that always prints
|
||||
255.
|
||||
|
||||
3) Why is the scale variable ignored on multiply?
|
||||
|
||||
That is the way POSIX specifics multiply. Reread the documentation for
|
||||
the multiply operation and see that multiply uses the scales of the
|
||||
numbers multiplied to determine the scale of the result.
|
||||
|
||||
4) bc's mod command is not working when I run with "bc -l".
|
||||
|
||||
bc's mod (%) command works like integer remainder when scale is 0.
|
||||
The -l flag sets scale to 20 and that chanes how a % b is computed.
|
||||
Read the man page for exact details.
|
||||
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
SUBDIRS = lib bc dc doc
|
||||
|
||||
MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
|
||||
stamp-h $(distdir).tar.gz h/number.h depcomp missing \
|
||||
bc/libmath.h
|
||||
|
||||
dist-hook:
|
||||
mkdir $(distdir)/h $(distdir)/Examples $(distdir)/Test
|
||||
cp -p $(srcdir)/h/*.h $(distdir)/h
|
||||
cp -p $(srcdir)/Examples/*.b $(distdir)/Examples
|
||||
cp -p $(srcdir)/Test/*.b $(srcdir)/Test/*.bc $(distdir)/Test
|
||||
cp -p $(srcdir)/Test/signum $(srcdir)/Test/timetest $(distdir)/Test
|
||||
cp -p $(srcdir)/lib/testmul.c $(distdir)/lib
|
||||
cp -p $(srcdir)/FAQ $(distdir)
|
||||
rm -f $(distdir)/bc/libmath.h
|
||||
|
||||
timetest:
|
||||
(cd lib; $(MAKE) specialnumber)
|
|
@ -0,0 +1,785 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = .
|
||||
DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
|
||||
$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/configure $(am__configure_deps) \
|
||||
$(srcdir)/config.h.in COPYING COPYING.LIB ar-lib compile \
|
||||
install-sh missing ylwrap
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
|
||||
configure.lineno config.status.lineno
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||
install-data-recursive install-dvi-recursive \
|
||||
install-exec-recursive install-html-recursive \
|
||||
install-info-recursive install-pdf-recursive \
|
||||
install-ps-recursive install-recursive installcheck-recursive \
|
||||
installdirs-recursive pdf-recursive ps-recursive \
|
||||
tags-recursive uninstall-recursive
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
am__recursive_targets = \
|
||||
$(RECURSIVE_TARGETS) \
|
||||
$(RECURSIVE_CLEAN_TARGETS) \
|
||||
$(am__extra_recursive_targets)
|
||||
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
|
||||
cscope distdir dist dist-all distcheck
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
|
||||
$(LISP)config.h.in
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
CSCOPE = cscope
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
am__remove_distdir = \
|
||||
if test -d "$(distdir)"; then \
|
||||
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
|
||||
&& rm -rf "$(distdir)" \
|
||||
|| { sleep 5 && rm -rf "$(distdir)"; }; \
|
||||
else :; fi
|
||||
am__post_remove_distdir = $(am__remove_distdir)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
|
||||
sed_rest='s,^[^/]*/*,,'; \
|
||||
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
|
||||
sed_butlast='s,/*[^/]*$$,,'; \
|
||||
while test -n "$$dir1"; do \
|
||||
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
|
||||
if test "$$first" != "."; then \
|
||||
if test "$$first" = ".."; then \
|
||||
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
|
||||
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
|
||||
else \
|
||||
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
|
||||
if test "$$first2" = "$$first"; then \
|
||||
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
|
||||
else \
|
||||
dir2="../$$dir2"; \
|
||||
fi; \
|
||||
dir0="$$dir0"/"$$first"; \
|
||||
fi; \
|
||||
fi; \
|
||||
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
|
||||
done; \
|
||||
reldir="$$dir2"
|
||||
DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
|
||||
GZIP_ENV = --best
|
||||
DIST_TARGETS = dist-bzip2 dist-gzip
|
||||
distuninstallcheck_listfiles = find . -type f -print
|
||||
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
|
||||
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
|
||||
distcleancheck_listfiles = find . -type f -print
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BC_VERSION = @BC_VERSION@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DC_VERSION = @DC_VERSION@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
READLINELIB = @READLINELIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
YACC = @YACC@
|
||||
YFLAGS = @YFLAGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
SUBDIRS = lib bc dc doc
|
||||
MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \
|
||||
stamp-h $(distdir).tar.gz h/number.h depcomp missing \
|
||||
bc/libmath.h
|
||||
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
am--refresh: Makefile
|
||||
@:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
|
||||
$(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
echo ' $(SHELL) ./config.status'; \
|
||||
$(SHELL) ./config.status;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
$(am__cd) $(srcdir) && $(AUTOCONF)
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
config.h: stamp-h1
|
||||
@test -f $@ || rm -f stamp-h1
|
||||
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
|
||||
|
||||
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
@rm -f stamp-h1
|
||||
cd $(top_builddir) && $(SHELL) ./config.status config.h
|
||||
$(srcdir)/config.h.in: $(am__configure_deps)
|
||||
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
|
||||
rm -f stamp-h1
|
||||
touch $@
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
|
||||
# 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.
|
||||
$(am__recursive_targets):
|
||||
@fail=; \
|
||||
if $(am__make_keepgoing); then \
|
||||
failcom='fail=yes'; \
|
||||
else \
|
||||
failcom='exit 1'; \
|
||||
fi; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-recursive
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-recursive
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscope: cscope.files
|
||||
test ! -s cscope.files \
|
||||
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
|
||||
clean-cscope:
|
||||
-rm -f cscope.files
|
||||
cscope.files: clean-cscope cscopelist
|
||||
cscopelist: cscopelist-recursive
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
$(am__remove_distdir)
|
||||
test -d "$(distdir)" || mkdir "$(distdir)"
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
$(am__make_dryrun) \
|
||||
|| test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
|
||||
$(am__relativize); \
|
||||
new_distdir=$$reldir; \
|
||||
dir1=$$subdir; dir2="$(top_distdir)"; \
|
||||
$(am__relativize); \
|
||||
new_top_distdir=$$reldir; \
|
||||
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
|
||||
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
|
||||
($(am__cd) $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$new_top_distdir" \
|
||||
distdir="$$new_distdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
am__skip_mode_fix=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$(top_distdir)" distdir="$(distdir)" \
|
||||
dist-hook
|
||||
-test -n "$(am__skip_mode_fix)" \
|
||||
|| find "$(distdir)" -type d ! -perm -755 \
|
||||
-exec chmod u+rwx,go+rx {} \; -o \
|
||||
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
|
||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||
|| chmod -R a+r "$(distdir)"
|
||||
dist-gzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
||||
$(am__post_remove_distdir)
|
||||
dist-bzip2: distdir
|
||||
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-lzip: distdir
|
||||
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-xz: distdir
|
||||
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-tarZ: distdir
|
||||
@echo WARNING: "Support for shar distribution archives is" \
|
||||
"deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-shar: distdir
|
||||
@echo WARNING: "Support for distribution archives compressed with" \
|
||||
"legacy program 'compress' is deprecated." >&2
|
||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist-zip: distdir
|
||||
-rm -f $(distdir).zip
|
||||
zip -rq $(distdir).zip $(distdir)
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
dist dist-all:
|
||||
$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
|
||||
$(am__post_remove_distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
case '$(DIST_ARCHIVES)' in \
|
||||
*.tar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||
*.tar.bz2*) \
|
||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||
*.tar.lz*) \
|
||||
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
|
||||
*.tar.xz*) \
|
||||
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
|
||||
*.tar.Z*) \
|
||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||
*.shar.gz*) \
|
||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
||||
*.zip*) \
|
||||
unzip $(distdir).zip ;;\
|
||||
esac
|
||||
chmod -R a-w $(distdir)
|
||||
chmod u+w $(distdir)
|
||||
mkdir $(distdir)/_build $(distdir)/_inst
|
||||
chmod a-w $(distdir)
|
||||
test -d $(distdir)/_build || exit 0; \
|
||||
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
|
||||
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
|
||||
&& am__cwd=`pwd` \
|
||||
&& $(am__cd) $(distdir)/_build \
|
||||
&& ../configure \
|
||||
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
|
||||
$(DISTCHECK_CONFIGURE_FLAGS) \
|
||||
--srcdir=.. --prefix="$$dc_install_base" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
|
||||
distuninstallcheck \
|
||||
&& chmod -R a-w "$$dc_install_base" \
|
||||
&& ({ \
|
||||
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
|
||||
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
|
||||
} || { rm -rf "$$dc_destdir"; exit 1; }) \
|
||||
&& rm -rf "$$dc_destdir" \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist \
|
||||
&& rm -rf $(DIST_ARCHIVES) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
|
||||
&& cd "$$am__cwd" \
|
||||
|| exit 1
|
||||
$(am__post_remove_distdir)
|
||||
@(echo "$(distdir) archives ready for distribution: "; \
|
||||
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
|
||||
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
|
||||
distuninstallcheck:
|
||||
@test -n '$(distuninstallcheck_dir)' || { \
|
||||
echo 'ERROR: trying to run $@ with an empty' \
|
||||
'$$(distuninstallcheck_dir)' >&2; \
|
||||
exit 1; \
|
||||
}; \
|
||||
$(am__cd) '$(distuninstallcheck_dir)' || { \
|
||||
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
|
||||
exit 1; \
|
||||
}; \
|
||||
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left after uninstall:" ; \
|
||||
if test -n "$(DESTDIR)"; then \
|
||||
echo " (check DESTDIR support)"; \
|
||||
fi ; \
|
||||
$(distuninstallcheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
distcleancheck: distclean
|
||||
@if test '$(srcdir)' = . ; then \
|
||||
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|
||||
|| { echo "ERROR: files left in build directory after distclean:" ; \
|
||||
$(distcleancheck_listfiles) ; \
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
-rm -rf $(top_srcdir)/autom4te.cache
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(am__recursive_targets) all install-am install-strip
|
||||
|
||||
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
|
||||
am--refresh check check-am clean clean-cscope clean-generic \
|
||||
cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
|
||||
dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \
|
||||
dist-zip distcheck distclean distclean-generic distclean-hdr \
|
||||
distclean-tags distcleancheck distdir distuninstallcheck dvi \
|
||||
dvi-am html html-am info info-am install install-am \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs installdirs-am \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am
|
||||
|
||||
|
||||
dist-hook:
|
||||
mkdir $(distdir)/h $(distdir)/Examples $(distdir)/Test
|
||||
cp -p $(srcdir)/h/*.h $(distdir)/h
|
||||
cp -p $(srcdir)/Examples/*.b $(distdir)/Examples
|
||||
cp -p $(srcdir)/Test/*.b $(srcdir)/Test/*.bc $(distdir)/Test
|
||||
cp -p $(srcdir)/Test/signum $(srcdir)/Test/timetest $(distdir)/Test
|
||||
cp -p $(srcdir)/lib/testmul.c $(distdir)/lib
|
||||
cp -p $(srcdir)/FAQ $(distdir)
|
||||
rm -f $(distdir)/bc/libmath.h
|
||||
|
||||
timetest:
|
||||
(cd lib; $(MAKE) specialnumber)
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -0,0 +1,99 @@
|
|||
This is GNU bc version 1.07.1. (And dc version 1.4.1)
|
||||
|
||||
Changes in bc from 1.07 to 1.07.1.
|
||||
Fixed ibase extension causing problems for read()
|
||||
Fixed parallel make problem.
|
||||
|
||||
Changes in dc 1.4 to 1.4.1.
|
||||
Fixed dc "Q" comanmd bug.
|
||||
|
||||
Changes in bc from 1.06 to 1.07.
|
||||
Added void functions.
|
||||
Bug fixes:
|
||||
fixes bug in load_code introduced by mathlib string storage in 1.06.
|
||||
fix to get long options working.
|
||||
signal code clean-up.
|
||||
fixed a bug in the AVL tree routines.
|
||||
fixed math library to work properly when called with ibase not 10.
|
||||
fixed a symbol table bug when using more than 32 names.
|
||||
removed a double free.
|
||||
Added base 17 to 36 for ibase.
|
||||
Fixed some memory leaks.
|
||||
Various small tweaks and doc bug fixes.
|
||||
|
||||
Changes in dc from 1.3 to 1.4:
|
||||
Recognize and handle tail recursion.
|
||||
Add 'r' and 'R' commands for stack manipulation.
|
||||
Finally fix dc to trap interrupts, like the documentation has said it
|
||||
should: aborts any executing macros, but does not exit the program.
|
||||
Bug fixes.
|
||||
Miscellaneous code clean-up.
|
||||
Changed to detect directories and generate errors.
|
||||
Detects and reports on any output errors; exits non-success.
|
||||
|
||||
Changes in dc from 1.2 to 1.3:
|
||||
Minor bug fixes.
|
||||
New multiply algorithm of bc.
|
||||
|
||||
Changes in bc from 1.05 to 1.06:
|
||||
New multiply algoirthm and many other changes in lib/number.c
|
||||
Function size now done dynamically.
|
||||
Function syntax in non-posix mode allows newlines in more places.
|
||||
Bug fixes:
|
||||
improved computation of j(n,x).
|
||||
enables readline only if interactive.
|
||||
for statment bug fixed.
|
||||
use int instead of char for readline char counts.
|
||||
improved cosine accuracy.
|
||||
|
||||
Changes in dc from 1.1 to 1.2:
|
||||
added !< != !> commands
|
||||
arrays now stack
|
||||
output is now line buffered, provided setvbuf() is available
|
||||
fixed known bugs in 'q', 'Q', 'a' commands, '-f' command-line option,
|
||||
and documentation
|
||||
changed the 'P' command's behavior on a numeric argument:
|
||||
due to popular demand it now does the equivalent of 'aP'
|
||||
(for small values)
|
||||
added new 'n' command to do what the old 'P' command did
|
||||
|
||||
Changes in bc from 1.04 to 1.05:
|
||||
Solaris makes work better.
|
||||
bug fixes
|
||||
stdout now always does line buffering.
|
||||
sqrt bug fixed for small numbers.
|
||||
readline (if support is compiled in) is enabled only for
|
||||
interactive executions of bc.
|
||||
|
||||
|
||||
This is GNU bc version 1.04. (And dc version 1.1)
|
||||
|
||||
Changes from 1.03
|
||||
|
||||
reorganization of source tree
|
||||
use of automake
|
||||
|
||||
new commands for dc (|, ~, r, a)
|
||||
new command line options for dc
|
||||
|
||||
fixed infinite loop in sqrt in bc
|
||||
fixed an I/O bug in bc
|
||||
made bc conform to POSIX for array parameters
|
||||
added long option support for bc
|
||||
new commandline options for bc (-q)
|
||||
added support for readline to bc (use configure --with-readline)
|
||||
command line argumens can now be taken from an environment variable
|
||||
|
||||
|
||||
Changes from 1.02
|
||||
|
||||
minor bug fixes in bc.
|
||||
|
||||
addition of Ken Pizzini's dc program that uses the GNU bc
|
||||
arbitrary precision arithmetic routines.
|
||||
|
||||
Changes from 1.01
|
||||
|
||||
minor bug fixes.
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
GNU bc version 1.07:
|
||||
|
||||
Extra configuration options:
|
||||
|
||||
--with-readline tells bc to use the readline package that allows
|
||||
for editing input lines when run interactive.
|
||||
|
||||
--with-editline tells bc to use the BSD editline package that
|
||||
allows for editing input lines when run interactive.
|
||||
|
||||
Extra make steps:
|
||||
|
||||
The simple make compiles a version of bc with fixed parameters
|
||||
for the recursive multiplication algorithm. The fixed parameter
|
||||
is the number of digits where a sequential algorithm is used
|
||||
instead of the recursive algorithm. It is set to a value that
|
||||
is known good on a couple of machines. (Sparc Ultra 10, Pentium
|
||||
II, 450.) I'm calling this point the crossover point.
|
||||
|
||||
To make a version of bc with a custom crossover point for your
|
||||
machine, do the following steps:
|
||||
|
||||
make timetest
|
||||
make
|
||||
|
||||
The timetest step takes a minimum of 10 minutes to complete.
|
||||
|
||||
|
||||
-------- Original comp.sources.reviewed README --------
|
||||
|
||||
Program: GNU bc
|
||||
Author: Philip A. Nelson
|
||||
E-mail: phil@cs.wwu.edu
|
||||
OS: UNIX (BSD, System V, MINIX, POSIX)
|
||||
Copying: GNU GPL version 2
|
||||
Copyright holder: Free Software Foundation, Inc.
|
||||
Version: bc version 1.01
|
||||
Required: vsprintf and vfprintf routines.
|
||||
Machines: It has been compiled and run on the following environments:
|
||||
BSD4.3 (VAX 11)
|
||||
MINIX 1.5 (IBM PC, both K&R and ANSI compilers)
|
||||
MINIX 1.5 (pc532)
|
||||
SUN-OS 4.1 (SUN 3 and SUN 4)
|
||||
SVR3V5 (Motorola 68K)
|
||||
SVR3.2 (3B2)
|
||||
SVR4.0.2 (a 386 box)
|
||||
ULTRIX 4.1 (DEC 5000)
|
||||
UTS (Amdahl)
|
||||
|
||||
bc is an arbitrary precision numeric processing language. Syntax is
|
||||
similar to C, but differs in many substantial areas. It supports
|
||||
interactive execution of statements. bc is a utility included in the
|
||||
POSIX P1003.2/D11 draft standard.
|
||||
|
||||
This version was written to be a POSIX compliant bc processor with
|
||||
several extensions to the draft standard. Option flags are available
|
||||
to cause warning or rejection of the extensions to the POSIX standard.
|
||||
For those who want only POSIX bc with no extensions, a grammar is
|
||||
provided for exactly the language described in the POSIX document.
|
||||
The grammar (sbc.y) comes from the POSIX document. The Makefile
|
||||
contains rules to make sbc. (for Standard BC)
|
||||
|
||||
Since the POSIX document does not specify how bc must be implemented,
|
||||
this version does not use the historical method of having bc be a
|
||||
compiler for the dc calculator. This version has a single executable
|
||||
that both compiles the language and runs the a resulting "byte code".
|
||||
The "byte code" is NOT the dc language.
|
||||
|
||||
Also, included in the initial distribution is the library file
|
||||
vfprintf.c for MINIX systems. My minix 1.5 did not have this file.
|
||||
Also, you should verify that vsprintf.c works correctly on your
|
||||
system.
|
||||
|
||||
The extensions add some features I think are missing. The major
|
||||
changes and additions for bc are (a) names are allowed to be full
|
||||
identifiers ([a-z][a-z0-9_]*), (b) addition of the &&, ||, and !
|
||||
operators, (c) allowing comparison and boolean operations in any
|
||||
expression, (d) addition of an else clause to the if statement, (e)
|
||||
addition of a new standard function "read()" that reads a number from
|
||||
the standard input under program control, (f) passing of arrays as
|
||||
parameters by variable, (g) addition of the "halt" statement that is
|
||||
an executable statement unlike the quit (i.e. "if (1 == 0) quit" will
|
||||
halt bc but "if (1 == 0) halt" will not halt bc.), and (h) the
|
||||
addition of the special variable "last" that is assigned the value of
|
||||
each print as the number is printed.
|
||||
-----------------------------------------------------------------------
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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[]);
|
|
@ -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
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
for (a=0; a<180; a+=.4) x=e(a)
|
||||
x
|
||||
quit
|
|
@ -0,0 +1,10 @@
|
|||
define f (x) {
|
||||
|
||||
if (x<=1) return(1)
|
||||
return (f(x-1)*x)
|
||||
}
|
||||
|
||||
for (a=1; a<600; a++) b=f(a)
|
||||
"length(b)= "; length(b)
|
||||
quit
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
scale = 50
|
||||
for (a=0; a<=100; a += 20) {
|
||||
for (b=0; b<=300; b += 20) x=j(a,b)
|
||||
x
|
||||
}
|
||||
quit
|
|
@ -0,0 +1,4 @@
|
|||
scale = 60
|
||||
for (a=1; a<100000000000000000000000000000000000000; a = a*2) x=l(a)
|
||||
x
|
||||
quit
|
|
@ -0,0 +1,13 @@
|
|||
scale = 20
|
||||
for (i=0; i<10000; i++) {
|
||||
for (j=1; j<100; j++) b=i*j
|
||||
}
|
||||
b
|
||||
for (i=0; i<10000; i++) {
|
||||
for (j=1000000000000000000000000000000000000000000000000000000000000000000; \
|
||||
j<1000000000000000000000000000000000000000000000000000000000000000100; \
|
||||
j++) b=i*j
|
||||
}
|
||||
b
|
||||
quit
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
for (i=0; i<1000; i++) a = 2^i;
|
||||
length(a)
|
||||
for (i=3000; i<3100; i++) a = 3^i;
|
||||
length(a)
|
||||
for (i=200; i<220; i++) a = (4^100)^i;
|
||||
length(a)
|
||||
quit
|
|
@ -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
|
||||
"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Time the functions.
|
||||
#
|
||||
SYSBC=/usr/bin/bc
|
||||
if [ x$BC = x ] ; then
|
||||
BC=../bc/bc
|
||||
fi
|
||||
for file in exp.b ln.b sine.b atan.b jn.b mul.b div.b raise.b sqrt.b fact.b
|
||||
do
|
||||
for prog in $SYSBC $BC $OTHERBC
|
||||
do
|
||||
echo Timing $file with $prog
|
||||
time $prog -l $file
|
||||
done
|
||||
done
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,270 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for Microsoft lib.exe
|
||||
|
||||
me=ar-lib
|
||||
scriptversion=2012-03-01.08; # UTC
|
||||
|
||||
# Copyright (C) 2010-2013 Free Software Foundation, Inc.
|
||||
# Written by Peter Rosin <peda@lysator.liu.se>.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
|
||||
# func_error message
|
||||
func_error ()
|
||||
{
|
||||
echo "$me: $1" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv in
|
||||
mingw)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_at_file at_file operation archive
|
||||
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
|
||||
# for each of them.
|
||||
# When interpreting the content of the @FILE, do NOT use func_file_conv,
|
||||
# since the user would need to supply preconverted file names to
|
||||
# binutils ar, at least for MinGW.
|
||||
func_at_file ()
|
||||
{
|
||||
operation=$2
|
||||
archive=$3
|
||||
at_file_contents=`cat "$1"`
|
||||
eval set x "$at_file_contents"
|
||||
shift
|
||||
|
||||
for member
|
||||
do
|
||||
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
|
||||
done
|
||||
}
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
func_error "no command. Try '$0 --help' for more information."
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<EOF
|
||||
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
|
||||
|
||||
Members may be specified in a file named with @FILE.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "$me, version $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test $# -lt 3; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
|
||||
AR=$1
|
||||
shift
|
||||
while :
|
||||
do
|
||||
if test $# -lt 2; then
|
||||
func_error "you must specify a program, an action and an archive"
|
||||
fi
|
||||
case $1 in
|
||||
-lib | -LIB \
|
||||
| -ltcg | -LTCG \
|
||||
| -machine* | -MACHINE* \
|
||||
| -subsystem* | -SUBSYSTEM* \
|
||||
| -verbose | -VERBOSE \
|
||||
| -wx* | -WX* )
|
||||
AR="$AR $1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
action=$1
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
orig_archive=$1
|
||||
shift
|
||||
func_file_conv "$orig_archive"
|
||||
archive=$file
|
||||
|
||||
# strip leading dash in $action
|
||||
action=${action#-}
|
||||
|
||||
delete=
|
||||
extract=
|
||||
list=
|
||||
quick=
|
||||
replace=
|
||||
index=
|
||||
create=
|
||||
|
||||
while test -n "$action"
|
||||
do
|
||||
case $action in
|
||||
d*) delete=yes ;;
|
||||
x*) extract=yes ;;
|
||||
t*) list=yes ;;
|
||||
q*) quick=yes ;;
|
||||
r*) replace=yes ;;
|
||||
s*) index=yes ;;
|
||||
S*) ;; # the index is always updated implicitly
|
||||
c*) create=yes ;;
|
||||
u*) ;; # TODO: don't ignore the update modifier
|
||||
v*) ;; # TODO: don't ignore the verbose modifier
|
||||
*)
|
||||
func_error "unknown action specified"
|
||||
;;
|
||||
esac
|
||||
action=${action#?}
|
||||
done
|
||||
|
||||
case $delete$extract$list$quick$replace,$index in
|
||||
yes,* | ,yes)
|
||||
;;
|
||||
yesyes*)
|
||||
func_error "more than one action specified"
|
||||
;;
|
||||
*)
|
||||
func_error "no action specified"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -n "$delete"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -REMOVE "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
elif test -n "$extract"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
if test $# -gt 0; then
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_at_file "${1#@}" -EXTRACT "$archive"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
|
||||
do
|
||||
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
|
||||
done
|
||||
fi
|
||||
|
||||
elif test -n "$quick$replace"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
if test -z "$create"; then
|
||||
echo "$me: creating $orig_archive"
|
||||
fi
|
||||
orig_archive=
|
||||
else
|
||||
orig_archive=$archive
|
||||
fi
|
||||
|
||||
for member
|
||||
do
|
||||
case $1 in
|
||||
@*)
|
||||
func_file_conv "${1#@}"
|
||||
set x "$@" "@$file"
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$1"
|
||||
set x "$@" "$file"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
shift
|
||||
done
|
||||
|
||||
if test -n "$orig_archive"; then
|
||||
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
|
||||
else
|
||||
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
|
||||
fi
|
||||
|
||||
elif test -n "$list"; then
|
||||
if test ! -f "$orig_archive"; then
|
||||
func_error "archive not found"
|
||||
fi
|
||||
$AR -NOLOGO -LIST "$archive" || exit $?
|
||||
fi
|
|
@ -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 \
|
||||
warranty.c
|
||||
|
||||
EXTRA_DIST = bc.h bcdefs.h const.h fix-libmath_h global.h libmath.b proto.h \
|
||||
sbc.y
|
||||
noinst_HEADERS = libmath.h
|
||||
|
||||
DISTCLEANFILES = sbc sbc.c sbc.h libmath.h
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in bc.c bc.h scan.c \
|
||||
bc.y bcdefs.h const.h execute.c fix-libmath_h \
|
||||
global.c global.h libmath.b load.c main.c \
|
||||
proto.h scan.l storage.c util.c
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/../h
|
||||
LIBBC = ../lib/libbc.a
|
||||
LIBL = @LEXLIB@
|
||||
LDADD = $(LIBBC) $(LIBL) @READLINELIB@
|
||||
|
||||
AM_YFLAGS = -d
|
||||
|
||||
AM_CFLAGS = @CFLAGS@
|
||||
|
||||
$(PROGRAMS): libmath.h $(LIBBC)
|
||||
|
||||
scan.o: bc.h
|
||||
global.o: libmath.h
|
||||
|
||||
fbcOBJ = main.o bc.o scan.o execute.o load.o storage.o util.o warranty.o
|
||||
|
||||
libmath.h: libmath.b $(fbcOBJ) $(LIBBC)
|
||||
echo '{0}' > libmath.h
|
||||
$(MAKE) global.o
|
||||
$(LINK) -o fbc $(fbcOBJ) global.o $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
|
||||
./fbc -c $(srcdir)/libmath.b </dev/null >libmath.h
|
||||
$(srcdir)/fix-libmath_h
|
||||
rm -f ./fbc ./global.o
|
||||
|
||||
sbcOBJ = main.o sbc.o scan.o execute.o global.o load.o storage.o util.o \
|
||||
warranty.o
|
||||
sbc.o: sbc.c
|
||||
sbc: $(sbcOBJ) $(LIBBC)
|
||||
$(LINK) $(sbcOBJ) $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
|
|
@ -0,0 +1,640 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
bin_PROGRAMS = bc$(EXEEXT)
|
||||
subdir = bc
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am bc.h bc.c \
|
||||
scan.c $(top_srcdir)/depcomp $(top_srcdir)/ylwrap \
|
||||
$(noinst_HEADERS)
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_bc_OBJECTS = main.$(OBJEXT) bc.$(OBJEXT) scan.$(OBJEXT) \
|
||||
execute.$(OBJEXT) load.$(OBJEXT) storage.$(OBJEXT) \
|
||||
util.$(OBJEXT) global.$(OBJEXT) warranty.$(OBJEXT)
|
||||
bc_OBJECTS = $(am_bc_OBJECTS)
|
||||
bc_LDADD = $(LDADD)
|
||||
am__DEPENDENCIES_1 =
|
||||
bc_DEPENDENCIES = $(LIBBC) $(am__DEPENDENCIES_1)
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
|
||||
AM_V_LEX = $(am__v_LEX_@AM_V@)
|
||||
am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
|
||||
am__v_LEX_0 = @echo " LEX " $@;
|
||||
am__v_LEX_1 =
|
||||
YLWRAP = $(top_srcdir)/ylwrap
|
||||
am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
|
||||
-e s/c++$$/h++/ -e s/c$$/h/
|
||||
YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
|
||||
AM_V_YACC = $(am__v_YACC_@AM_V@)
|
||||
am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
|
||||
am__v_YACC_0 = @echo " YACC " $@;
|
||||
am__v_YACC_1 =
|
||||
SOURCES = $(bc_SOURCES)
|
||||
DIST_SOURCES = $(bc_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
HEADERS = $(noinst_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BC_VERSION = @BC_VERSION@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DC_VERSION = @DC_VERSION@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
READLINELIB = @READLINELIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
YACC = @YACC@
|
||||
YFLAGS = @YFLAGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
bc_SOURCES = main.c bc.y scan.l execute.c load.c storage.c util.c global.c \
|
||||
warranty.c
|
||||
|
||||
EXTRA_DIST = bc.h bcdefs.h const.h fix-libmath_h global.h libmath.b proto.h \
|
||||
sbc.y
|
||||
|
||||
noinst_HEADERS = libmath.h
|
||||
DISTCLEANFILES = sbc sbc.c sbc.h libmath.h
|
||||
MAINTAINERCLEANFILES = Makefile.in bc.c bc.h scan.c \
|
||||
bc.y bcdefs.h const.h execute.c fix-libmath_h \
|
||||
global.c global.h libmath.b load.c main.c \
|
||||
proto.h scan.l storage.c util.c
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir) -I$(srcdir)/../h
|
||||
LIBBC = ../lib/libbc.a
|
||||
LIBL = @LEXLIB@
|
||||
LDADD = $(LIBBC) $(LIBL) @READLINELIB@
|
||||
AM_YFLAGS = -d
|
||||
AM_CFLAGS = @CFLAGS@
|
||||
fbcOBJ = main.o bc.o scan.o execute.o load.o storage.o util.o warranty.o
|
||||
sbcOBJ = main.o sbc.o scan.o execute.o global.o load.o storage.o util.o \
|
||||
warranty.o
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .l .o .obj .y
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bc/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu bc/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
bc.h: bc.c
|
||||
@if test ! -f $@; then rm -f bc.c; else :; fi
|
||||
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) bc.c; else :; fi
|
||||
|
||||
bc$(EXEEXT): $(bc_OBJECTS) $(bc_DEPENDENCIES) $(EXTRA_bc_DEPENDENCIES)
|
||||
@rm -f bc$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(bc_OBJECTS) $(bc_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execute.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/global.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scan.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/warranty.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.l.c:
|
||||
$(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
|
||||
|
||||
.y.c:
|
||||
$(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS) $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-rm -f bc.c
|
||||
-rm -f bc.h
|
||||
-rm -f scan.c
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
|
||||
clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \
|
||||
distclean distclean-compile distclean-generic distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-binPROGRAMS install-data install-data-am \
|
||||
install-dvi install-dvi-am install-exec install-exec-am \
|
||||
install-html install-html-am install-info install-info-am \
|
||||
install-man install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
|
||||
ps ps-am tags tags-am uninstall uninstall-am \
|
||||
uninstall-binPROGRAMS
|
||||
|
||||
|
||||
$(PROGRAMS): libmath.h $(LIBBC)
|
||||
|
||||
scan.o: bc.h
|
||||
global.o: libmath.h
|
||||
|
||||
libmath.h: libmath.b $(fbcOBJ) $(LIBBC)
|
||||
echo '{0}' > libmath.h
|
||||
$(MAKE) global.o
|
||||
$(LINK) -o fbc $(fbcOBJ) global.o $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
|
||||
./fbc -c $(srcdir)/libmath.b </dev/null >libmath.h
|
||||
$(srcdir)/fix-libmath_h
|
||||
rm -f ./fbc ./global.o
|
||||
sbc.o: sbc.c
|
||||
sbc: $(sbcOBJ) $(LIBBC)
|
||||
$(LINK) $(sbcOBJ) $(LIBBC) $(LIBL) $(READLINELIB) $(LIBS)
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -0,0 +1,146 @@
|
|||
/* A Bison parser, made by GNU Bison 3.0.2. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2013 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
#ifndef YY_YY_BC_H_INCLUDED
|
||||
# define YY_YY_BC_H_INCLUDED
|
||||
/* Debug traces. */
|
||||
#ifndef YYDEBUG
|
||||
# define YYDEBUG 0
|
||||
#endif
|
||||
#if YYDEBUG
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
/* Token type. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
enum yytokentype
|
||||
{
|
||||
ENDOFLINE = 258,
|
||||
AND = 259,
|
||||
OR = 260,
|
||||
NOT = 261,
|
||||
STRING = 262,
|
||||
NAME = 263,
|
||||
NUMBER = 264,
|
||||
ASSIGN_OP = 265,
|
||||
REL_OP = 266,
|
||||
INCR_DECR = 267,
|
||||
Define = 268,
|
||||
Break = 269,
|
||||
Quit = 270,
|
||||
Length = 271,
|
||||
Return = 272,
|
||||
For = 273,
|
||||
If = 274,
|
||||
While = 275,
|
||||
Sqrt = 276,
|
||||
Else = 277,
|
||||
Scale = 278,
|
||||
Ibase = 279,
|
||||
Obase = 280,
|
||||
Auto = 281,
|
||||
Read = 282,
|
||||
Random = 283,
|
||||
Warranty = 284,
|
||||
Halt = 285,
|
||||
Last = 286,
|
||||
Continue = 287,
|
||||
Print = 288,
|
||||
Limits = 289,
|
||||
UNARY_MINUS = 290,
|
||||
HistoryVar = 291,
|
||||
Void = 292
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define ENDOFLINE 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 Random 283
|
||||
#define Warranty 284
|
||||
#define Halt 285
|
||||
#define Last 286
|
||||
#define Continue 287
|
||||
#define Print 288
|
||||
#define Limits 289
|
||||
#define UNARY_MINUS 290
|
||||
#define HistoryVar 291
|
||||
#define Void 292
|
||||
|
||||
/* Value type. */
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
union YYSTYPE
|
||||
{
|
||||
#line 52 "../../bc/bc.y" /* yacc.c:1909 */
|
||||
|
||||
char *s_value;
|
||||
char c_value;
|
||||
int i_value;
|
||||
arg_list *a_value;
|
||||
|
||||
|
||||
#line 136 "bc.h" /* yacc.c:1909 */
|
||||
};
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
#endif
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
int yyparse (void);
|
||||
|
||||
#endif /* !YY_YY_BC_H_INCLUDED */
|
|
@ -0,0 +1,793 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* bc.y: The grammar for a POSIX compatable bc processor with some
|
||||
extensions to the language. */
|
||||
|
||||
%{
|
||||
|
||||
#include "bcdefs.h"
|
||||
#include "global.h"
|
||||
#include "proto.h"
|
||||
|
||||
/* current function number. */
|
||||
int cur_func = -1;
|
||||
|
||||
/* Expression encoded information -- See comment at expression rules. */
|
||||
#define EX_ASSGN 0
|
||||
#define EX_REG 1
|
||||
#define EX_COMP 2
|
||||
#define EX_PAREN 4
|
||||
#define EX_VOID 8
|
||||
#define EX_EMPTY 16
|
||||
|
||||
%}
|
||||
|
||||
%start program
|
||||
|
||||
%union {
|
||||
char *s_value;
|
||||
char c_value;
|
||||
int i_value;
|
||||
arg_list *a_value;
|
||||
}
|
||||
|
||||
/* Extensions over POSIX bc.
|
||||
a) NAME was LETTER. This grammar allows longer names.
|
||||
Single letter names will still work.
|
||||
b) Relational_expression allowed only one comparison.
|
||||
This grammar has added boolean expressions with
|
||||
&& (and) || (or) and ! (not) and allowed all of them in
|
||||
full expressions.
|
||||
c) Added an else to the if.
|
||||
d) Call by variable array parameters
|
||||
e) read() procedure that reads a number under program control from stdin.
|
||||
f) halt statement that halts the the program under program control. It
|
||||
is an executed statement.
|
||||
g) continue statement for for loops.
|
||||
h) optional expressions in the for loop.
|
||||
i) print statement to print multiple numbers per line.
|
||||
j) warranty statement to print an extended warranty notice.
|
||||
k) limits statement to print the processor's limits.
|
||||
l) void functions.
|
||||
*/
|
||||
|
||||
%token <i_value> ENDOFLINE AND OR NOT
|
||||
%token <s_value> STRING NAME NUMBER
|
||||
/* '-', '+' are tokens themselves */
|
||||
/* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
|
||||
%token <c_value> ASSIGN_OP
|
||||
/* '==', '<=', '>=', '!=', '<', '>' */
|
||||
%token <s_value> REL_OP
|
||||
/* '++', '--' */
|
||||
%token <c_value> INCR_DECR
|
||||
/* 'define', 'break', 'quit', 'length' */
|
||||
%token <i_value> Define Break Quit Length
|
||||
/* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
|
||||
%token <i_value> Return For If While Sqrt Else
|
||||
/* 'scale', 'ibase', 'obase', 'auto', 'read', 'random' */
|
||||
%token <i_value> Scale Ibase Obase Auto Read Random
|
||||
/* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
|
||||
%token <i_value> Warranty Halt Last Continue Print Limits
|
||||
/* 'history', 'void' */
|
||||
%token <i_value> UNARY_MINUS HistoryVar Void
|
||||
|
||||
|
||||
/* Types of all other things. */
|
||||
%type <i_value> expression return_expression named_expression opt_expression
|
||||
%type <c_value> '+' '-' '*' '/' '%'
|
||||
%type <a_value> opt_parameter_list opt_auto_define_list define_list
|
||||
%type <a_value> opt_argument_list argument_list
|
||||
%type <i_value> program input_item semicolon_list statement_list
|
||||
%type <i_value> statement function statement_or_error required_eol
|
||||
%type <i_value> opt_void
|
||||
|
||||
/* precedence */
|
||||
%left OR
|
||||
%left AND
|
||||
%nonassoc NOT
|
||||
%left REL_OP
|
||||
%right ASSIGN_OP
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%right '^'
|
||||
%nonassoc UNARY_MINUS
|
||||
%nonassoc INCR_DECR
|
||||
|
||||
%%
|
||||
program : /* empty */
|
||||
{
|
||||
$$ = 0;
|
||||
if (interactive && !quiet)
|
||||
{
|
||||
show_bc_version ();
|
||||
welcome ();
|
||||
}
|
||||
}
|
||||
| program input_item
|
||||
;
|
||||
input_item : semicolon_list ENDOFLINE
|
||||
{ run_code (); }
|
||||
| function
|
||||
{ run_code (); }
|
||||
| error ENDOFLINE
|
||||
{
|
||||
yyerrok;
|
||||
init_gen ();
|
||||
}
|
||||
;
|
||||
opt_newline : /* empty */
|
||||
| ENDOFLINE
|
||||
{ ct_warn ("newline not allowed"); }
|
||||
;
|
||||
semicolon_list : /* empty */
|
||||
{ $$ = 0; }
|
||||
| statement_or_error
|
||||
| semicolon_list ';' statement_or_error
|
||||
| semicolon_list ';'
|
||||
;
|
||||
statement_list : /* empty */
|
||||
{ $$ = 0; }
|
||||
| statement_or_error
|
||||
| statement_list ENDOFLINE
|
||||
| statement_list ENDOFLINE statement_or_error
|
||||
| statement_list ';'
|
||||
| statement_list ';' statement
|
||||
;
|
||||
statement_or_error : statement
|
||||
| error statement
|
||||
{ $$ = $2; }
|
||||
;
|
||||
statement : Warranty
|
||||
{ warranty (""); }
|
||||
| Limits
|
||||
{ limits (); }
|
||||
| expression
|
||||
{
|
||||
if ($1 & EX_COMP)
|
||||
ct_warn ("comparison in expression");
|
||||
if ($1 & EX_REG)
|
||||
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
|
||||
{
|
||||
snprintf (genstr, genlen, "J%1d:",
|
||||
break_label);
|
||||
generate (genstr);
|
||||
}
|
||||
}
|
||||
| Continue
|
||||
{
|
||||
ct_warn ("Continue statement");
|
||||
if (continue_label == 0)
|
||||
yyerror ("Continue outside a for");
|
||||
else
|
||||
{
|
||||
snprintf (genstr, genlen, "J%1d:",
|
||||
continue_label);
|
||||
generate (genstr);
|
||||
}
|
||||
}
|
||||
| Quit
|
||||
{ bc_exit (0); }
|
||||
| Halt
|
||||
{ generate ("h"); }
|
||||
| Return return_expression
|
||||
{ generate ("R"); }
|
||||
| For
|
||||
{
|
||||
$1 = break_label;
|
||||
break_label = next_label++;
|
||||
}
|
||||
'(' opt_expression ';'
|
||||
{
|
||||
if ($4 & EX_COMP)
|
||||
ct_warn ("Comparison in first for expression");
|
||||
if ($4 & EX_VOID)
|
||||
yyerror ("first expression is void");
|
||||
if (!($4 & EX_EMPTY))
|
||||
generate ("p");
|
||||
$4 = next_label++;
|
||||
snprintf (genstr, genlen, "N%1d:", $4);
|
||||
generate (genstr);
|
||||
}
|
||||
opt_expression ';'
|
||||
{
|
||||
if ($7 & EX_VOID)
|
||||
yyerror ("second expression is void");
|
||||
if ($7 & EX_EMPTY ) generate ("1");
|
||||
$7 = next_label++;
|
||||
snprintf (genstr, genlen, "B%1d:J%1d:", $7,
|
||||
break_label);
|
||||
generate (genstr);
|
||||
$<i_value>$ = continue_label;
|
||||
continue_label = next_label++;
|
||||
snprintf (genstr, genlen, "N%1d:",
|
||||
continue_label);
|
||||
generate (genstr);
|
||||
}
|
||||
opt_expression ')'
|
||||
{
|
||||
if ($10 & EX_COMP)
|
||||
ct_warn ("Comparison in third for expression");
|
||||
if ($10 & EX_VOID)
|
||||
yyerror ("third expression is void");
|
||||
if ($10 & EX_EMPTY)
|
||||
snprintf (genstr, genlen, "J%1d:N%1d:", $4, $7);
|
||||
else
|
||||
snprintf (genstr, genlen, "pJ%1d:N%1d:", $4, $7);
|
||||
generate (genstr);
|
||||
}
|
||||
opt_newline statement
|
||||
{
|
||||
snprintf (genstr, genlen, "J%1d:N%1d:",
|
||||
continue_label, break_label);
|
||||
generate (genstr);
|
||||
break_label = $1;
|
||||
continue_label = $<i_value>9;
|
||||
}
|
||||
| If '(' expression ')'
|
||||
{
|
||||
if ($3 & EX_VOID)
|
||||
yyerror ("void expression");
|
||||
$3 = if_label;
|
||||
if_label = next_label++;
|
||||
snprintf (genstr, genlen, "Z%1d:", if_label);
|
||||
generate (genstr);
|
||||
}
|
||||
opt_newline statement opt_else
|
||||
{
|
||||
snprintf (genstr, genlen, "N%1d:", if_label);
|
||||
generate (genstr);
|
||||
if_label = $3;
|
||||
}
|
||||
| While
|
||||
{
|
||||
$1 = continue_label;
|
||||
continue_label = next_label++;
|
||||
snprintf (genstr, genlen, "N%1d:",
|
||||
continue_label);
|
||||
generate (genstr);
|
||||
}
|
||||
'(' expression
|
||||
{
|
||||
if ($4 & EX_VOID)
|
||||
yyerror ("void expression");
|
||||
$4 = break_label;
|
||||
break_label = next_label++;
|
||||
snprintf (genstr, genlen, "Z%1d:", break_label);
|
||||
generate (genstr);
|
||||
}
|
||||
')' opt_newline statement
|
||||
{
|
||||
snprintf (genstr, genlen, "J%1d:N%1d:",
|
||||
continue_label, break_label);
|
||||
generate (genstr);
|
||||
break_label = $4;
|
||||
continue_label = $1;
|
||||
}
|
||||
| '{' statement_list '}'
|
||||
{ $$ = 0; }
|
||||
| Print
|
||||
{ ct_warn ("print statement"); }
|
||||
print_list
|
||||
;
|
||||
print_list : print_element
|
||||
| print_element ',' print_list
|
||||
;
|
||||
print_element : STRING
|
||||
{
|
||||
generate ("O");
|
||||
generate ($1);
|
||||
free ($1);
|
||||
}
|
||||
| expression
|
||||
{
|
||||
if ($1 & EX_VOID)
|
||||
yyerror ("void expression in print");
|
||||
generate ("P");
|
||||
}
|
||||
;
|
||||
opt_else : /* nothing */
|
||||
| Else
|
||||
{
|
||||
ct_warn ("else clause in if statement");
|
||||
$1 = next_label++;
|
||||
snprintf (genstr, genlen, "J%d:N%1d:", $1,
|
||||
if_label);
|
||||
generate (genstr);
|
||||
if_label = $1;
|
||||
}
|
||||
opt_newline statement
|
||||
;
|
||||
function : Define opt_void NAME '(' opt_parameter_list ')' opt_newline
|
||||
'{' required_eol opt_auto_define_list
|
||||
{ char *params, *autos;
|
||||
/* Check auto list against parameter list? */
|
||||
check_params ($5,$10);
|
||||
params = arg_str ($5);
|
||||
autos = arg_str ($10);
|
||||
set_genstr_size (30 + strlen (params)
|
||||
+ strlen (autos));
|
||||
cur_func = lookup($3,FUNCTDEF);
|
||||
snprintf (genstr, genlen, "F%d,%s.%s[", cur_func,
|
||||
params, autos);
|
||||
generate (genstr);
|
||||
functions[cur_func].f_void = $2;
|
||||
free_args ($5);
|
||||
free_args ($10);
|
||||
$1 = next_label;
|
||||
next_label = 1;
|
||||
}
|
||||
statement_list /* ENDOFLINE */ '}'
|
||||
{
|
||||
generate ("0R]");
|
||||
next_label = $1;
|
||||
cur_func = -1;
|
||||
}
|
||||
;
|
||||
opt_void : /* empty */
|
||||
{ $$ = 0; }
|
||||
| Void
|
||||
{
|
||||
$$ = 1;
|
||||
ct_warn ("void functions");
|
||||
}
|
||||
;
|
||||
opt_parameter_list : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| define_list
|
||||
;
|
||||
opt_auto_define_list : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| Auto define_list ENDOFLINE
|
||||
{ $$ = $2; }
|
||||
| Auto define_list ';'
|
||||
{ $$ = $2; }
|
||||
;
|
||||
define_list : NAME
|
||||
{ $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE);}
|
||||
| NAME '[' ']'
|
||||
{ $$ = nextarg (NULL, lookup ($1,ARRAY), FALSE); }
|
||||
| '*' NAME '[' ']'
|
||||
{ $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
|
||||
ct_warn ("Call by variable arrays");
|
||||
}
|
||||
| '&' NAME '[' ']'
|
||||
{ $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE);
|
||||
ct_warn ("Call by variable arrays");
|
||||
}
|
||||
| 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);
|
||||
ct_warn ("Call by variable arrays");
|
||||
}
|
||||
| define_list ',' '&' NAME '[' ']'
|
||||
{ $$ = nextarg ($1, lookup ($4,ARRAY), TRUE);
|
||||
ct_warn ("Call by variable arrays");
|
||||
}
|
||||
;
|
||||
opt_argument_list : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| argument_list
|
||||
;
|
||||
argument_list : expression
|
||||
{
|
||||
if ($1 & EX_COMP)
|
||||
ct_warn ("comparison in argument");
|
||||
if ($1 & EX_VOID)
|
||||
yyerror ("void argument");
|
||||
$$ = nextarg (NULL,0,FALSE);
|
||||
}
|
||||
| NAME '[' ']'
|
||||
{
|
||||
snprintf (genstr, genlen, "K%d:",
|
||||
-lookup ($1,ARRAY));
|
||||
generate (genstr);
|
||||
$$ = nextarg (NULL,1,FALSE);
|
||||
}
|
||||
| argument_list ',' expression
|
||||
{
|
||||
if ($3 & EX_COMP)
|
||||
ct_warn ("comparison in argument");
|
||||
if ($3 & EX_VOID)
|
||||
yyerror ("void argument");
|
||||
$$ = nextarg ($1,0,FALSE);
|
||||
}
|
||||
| argument_list ',' NAME '[' ']'
|
||||
{
|
||||
snprintf (genstr, genlen, "K%d:",
|
||||
-lookup ($3,ARRAY));
|
||||
generate (genstr);
|
||||
$$ = nextarg ($1,1,FALSE);
|
||||
}
|
||||
;
|
||||
|
||||
/* Expression lval meanings! (Bits mean something!) (See defines above)
|
||||
* 0 => Top op is assignment.
|
||||
* 1 => Top op is not assignment.
|
||||
* 2 => Comparison is somewhere in expression.
|
||||
* 4 => Expression is in parenthesis.
|
||||
* 8 => Expression is void!
|
||||
* 16 => Empty optional expression.
|
||||
*/
|
||||
|
||||
opt_expression : /* empty */
|
||||
{
|
||||
$$ = EX_EMPTY;
|
||||
ct_warn ("Missing expression in for statement");
|
||||
}
|
||||
| expression
|
||||
;
|
||||
return_expression : /* empty */
|
||||
{
|
||||
$$ = 0;
|
||||
generate ("0");
|
||||
if (cur_func == -1)
|
||||
yyerror("Return outside of a function.");
|
||||
}
|
||||
| expression
|
||||
{
|
||||
if ($1 & EX_COMP)
|
||||
ct_warn ("comparison in return expresion");
|
||||
if (!($1 & EX_PAREN))
|
||||
ct_warn ("return expression requires parenthesis");
|
||||
if ($1 & EX_VOID)
|
||||
yyerror("return requires non-void expression");
|
||||
if (cur_func == -1)
|
||||
yyerror("Return outside of a function.");
|
||||
else if (functions[cur_func].f_void)
|
||||
yyerror("Return expression in a void function.");
|
||||
}
|
||||
;
|
||||
expression : named_expression ASSIGN_OP
|
||||
{
|
||||
if ($2 != '=')
|
||||
{
|
||||
if ($1 < 0)
|
||||
snprintf (genstr, genlen, "DL%d:", -$1);
|
||||
else
|
||||
snprintf (genstr, genlen, "l%d:", $1);
|
||||
generate (genstr);
|
||||
}
|
||||
}
|
||||
expression
|
||||
{
|
||||
if ($4 & EX_ASSGN)
|
||||
ct_warn("comparison in assignment");
|
||||
if ($4 & EX_VOID)
|
||||
yyerror("Assignment of a void expression");
|
||||
if ($2 != '=')
|
||||
{
|
||||
snprintf (genstr, genlen, "%c", $2);
|
||||
generate (genstr);
|
||||
}
|
||||
if ($1 < 0)
|
||||
snprintf (genstr, genlen, "S%d:", -$1);
|
||||
else
|
||||
snprintf (genstr, genlen, "s%d:", $1);
|
||||
generate (genstr);
|
||||
$$ = EX_ASSGN;
|
||||
}
|
||||
| expression AND
|
||||
{
|
||||
ct_warn("&& operator");
|
||||
$2 = next_label++;
|
||||
snprintf (genstr, genlen, "DZ%d:p", $2);
|
||||
generate (genstr);
|
||||
}
|
||||
expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($4 & EX_VOID))
|
||||
yyerror ("void expression with &&");
|
||||
snprintf (genstr, genlen, "DZ%d:p1N%d:", $2, $2);
|
||||
generate (genstr);
|
||||
$$ = ($1 | $4) & ~EX_PAREN;
|
||||
}
|
||||
| expression OR
|
||||
{
|
||||
ct_warn("|| operator");
|
||||
$2 = next_label++;
|
||||
snprintf (genstr, genlen, "B%d:", $2);
|
||||
generate (genstr);
|
||||
}
|
||||
expression
|
||||
{
|
||||
int tmplab;
|
||||
if (($1 & EX_VOID) || ($4 & EX_VOID))
|
||||
yyerror ("void expression with ||");
|
||||
tmplab = next_label++;
|
||||
snprintf (genstr, genlen, "B%d:0J%d:N%d:1N%d:",
|
||||
$2, tmplab, $2, tmplab);
|
||||
generate (genstr);
|
||||
$$ = ($1 | $4) & ~EX_PAREN;
|
||||
}
|
||||
| NOT expression
|
||||
{
|
||||
if ($2 & EX_VOID)
|
||||
yyerror ("void expression with !");
|
||||
$$ = $2 & ~EX_PAREN;
|
||||
ct_warn("! operator");
|
||||
generate ("!");
|
||||
}
|
||||
| expression REL_OP expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with comparison");
|
||||
$$ = EX_REG | EX_COMP;
|
||||
switch (*($2))
|
||||
{
|
||||
case '=':
|
||||
generate ("=");
|
||||
break;
|
||||
|
||||
case '!':
|
||||
generate ("#");
|
||||
break;
|
||||
|
||||
case '<':
|
||||
if ($2[1] == '=')
|
||||
generate ("{");
|
||||
else
|
||||
generate ("<");
|
||||
break;
|
||||
|
||||
case '>':
|
||||
if ($2[1] == '=')
|
||||
generate ("}");
|
||||
else
|
||||
generate (">");
|
||||
break;
|
||||
}
|
||||
free($2);
|
||||
}
|
||||
| expression '+' expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with +");
|
||||
generate ("+");
|
||||
$$ = ($1 | $3) & ~EX_PAREN;
|
||||
}
|
||||
| expression '-' expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with -");
|
||||
generate ("-");
|
||||
$$ = ($1 | $3) & ~EX_PAREN;
|
||||
}
|
||||
| expression '*' expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with *");
|
||||
generate ("*");
|
||||
$$ = ($1 | $3) & ~EX_PAREN;
|
||||
}
|
||||
| expression '/' expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with /");
|
||||
generate ("/");
|
||||
$$ = ($1 | $3) & ~EX_PAREN;
|
||||
}
|
||||
| expression '%' expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with %");
|
||||
generate ("%");
|
||||
$$ = ($1 | $3) & ~EX_PAREN;
|
||||
}
|
||||
| expression '^' expression
|
||||
{
|
||||
if (($1 & EX_VOID) || ($3 & EX_VOID))
|
||||
yyerror ("void expression with ^");
|
||||
generate ("^");
|
||||
$$ = ($1 | $3) & ~EX_PAREN;
|
||||
}
|
||||
| '-' expression %prec UNARY_MINUS
|
||||
{
|
||||
if ($2 & EX_VOID)
|
||||
yyerror ("void expression with unary -");
|
||||
generate ("n");
|
||||
$$ = $2 & ~EX_PAREN;
|
||||
}
|
||||
| named_expression
|
||||
{
|
||||
$$ = EX_REG;
|
||||
if ($1 < 0)
|
||||
snprintf (genstr, genlen, "L%d:", -$1);
|
||||
else
|
||||
snprintf (genstr, genlen, "l%d:", $1);
|
||||
generate (genstr);
|
||||
}
|
||||
| NUMBER
|
||||
{
|
||||
int len = strlen($1);
|
||||
$$ = EX_REG;
|
||||
if (len == 1 && *$1 == '0')
|
||||
generate ("0");
|
||||
else if (len == 1 && *$1 == '1')
|
||||
generate ("1");
|
||||
else
|
||||
{
|
||||
generate ("K");
|
||||
generate ($1);
|
||||
generate (":");
|
||||
}
|
||||
free ($1);
|
||||
}
|
||||
| '(' expression ')'
|
||||
{
|
||||
if ($2 & EX_VOID)
|
||||
yyerror ("void expression in parenthesis");
|
||||
$$ = $2 | EX_REG | EX_PAREN;
|
||||
}
|
||||
| NAME '(' opt_argument_list ')'
|
||||
{ int fn;
|
||||
fn = lookup ($1,FUNCT);
|
||||
if (functions[fn].f_void)
|
||||
$$ = EX_VOID;
|
||||
else
|
||||
$$ = EX_REG;
|
||||
if ($3 != NULL)
|
||||
{ char *params = call_str ($3);
|
||||
set_genstr_size (20 + strlen (params));
|
||||
snprintf (genstr, genlen, "C%d,%s:", fn,
|
||||
params);
|
||||
free_args ($3);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf (genstr, genlen, "C%d:", fn);
|
||||
}
|
||||
generate (genstr);
|
||||
}
|
||||
| INCR_DECR named_expression
|
||||
{
|
||||
$$ = EX_REG;
|
||||
if ($2 < 0)
|
||||
{
|
||||
if ($1 == '+')
|
||||
snprintf (genstr, genlen, "DA%d:L%d:", -$2, -$2);
|
||||
else
|
||||
snprintf (genstr, genlen, "DM%d:L%d:", -$2, -$2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($1 == '+')
|
||||
snprintf (genstr, genlen, "i%d:l%d:", $2, $2);
|
||||
else
|
||||
snprintf (genstr, genlen, "d%d:l%d:", $2, $2);
|
||||
}
|
||||
generate (genstr);
|
||||
}
|
||||
| named_expression INCR_DECR
|
||||
{
|
||||
$$ = EX_REG;
|
||||
if ($1 < 0)
|
||||
{
|
||||
snprintf (genstr, genlen, "DL%d:x", -$1);
|
||||
generate (genstr);
|
||||
if ($2 == '+')
|
||||
snprintf (genstr, genlen, "A%d:", -$1);
|
||||
else
|
||||
snprintf (genstr, genlen, "M%d:", -$1);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf (genstr, genlen, "l%d:", $1);
|
||||
generate (genstr);
|
||||
if ($2 == '+')
|
||||
snprintf (genstr, genlen, "i%d:", $1);
|
||||
else
|
||||
snprintf (genstr, genlen, "d%d:", $1);
|
||||
}
|
||||
generate (genstr);
|
||||
}
|
||||
| Length '(' expression ')'
|
||||
{
|
||||
if ($3 & EX_VOID)
|
||||
yyerror ("void expression in length()");
|
||||
generate ("cL");
|
||||
$$ = EX_REG;
|
||||
}
|
||||
| Sqrt '(' expression ')'
|
||||
{
|
||||
if ($3 & EX_VOID)
|
||||
yyerror ("void expression in sqrt()");
|
||||
generate ("cR");
|
||||
$$ = EX_REG;
|
||||
}
|
||||
| Scale '(' expression ')'
|
||||
{
|
||||
if ($3 & EX_VOID)
|
||||
yyerror ("void expression in scale()");
|
||||
generate ("cS");
|
||||
$$ = EX_REG;
|
||||
}
|
||||
| Read '(' ')'
|
||||
{
|
||||
ct_warn ("read function");
|
||||
generate ("cI");
|
||||
$$ = EX_REG;
|
||||
}
|
||||
| Random '(' ')'
|
||||
{
|
||||
ct_warn ("random function");
|
||||
generate ("cX");
|
||||
$$ = EX_REG;
|
||||
}
|
||||
;
|
||||
named_expression : NAME
|
||||
{ $$ = lookup($1,SIMPLE); }
|
||||
| NAME '[' expression ']'
|
||||
{
|
||||
if ($3 & EX_VOID)
|
||||
yyerror("void expression as subscript");
|
||||
if ($3 & EX_COMP)
|
||||
ct_warn("comparison in subscript");
|
||||
$$ = lookup($1,ARRAY);
|
||||
}
|
||||
| Ibase
|
||||
{ $$ = 0; }
|
||||
| Obase
|
||||
{ $$ = 1; }
|
||||
| Scale
|
||||
{ $$ = 2; }
|
||||
| HistoryVar
|
||||
{ $$ = 3;
|
||||
ct_warn ("History variable");
|
||||
}
|
||||
| Last
|
||||
{ $$ = 4;
|
||||
ct_warn ("Last variable");
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
required_eol : { ct_warn ("End of line required"); }
|
||||
| ENDOFLINE
|
||||
| required_eol ENDOFLINE
|
||||
{ ct_warn ("Too many end of lines"); }
|
||||
;
|
||||
|
||||
%%
|
|
@ -0,0 +1,200 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* bcdefs.h: The single file to include all constants and type definitions. */
|
||||
|
||||
/* Include the configuration file. */
|
||||
#include "config.h"
|
||||
|
||||
/* Standard includes for all files. */
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
#include <histedit.h>
|
||||
#endif
|
||||
|
||||
#if defined(READLINE)
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
/* Initialization magic ... */
|
||||
#ifdef _GLOBAL_C
|
||||
#define EXTERN
|
||||
#define INIT(x) = x
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#define INIT(x)
|
||||
#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
|
||||
{
|
||||
unsigned 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_void; /* Is this function a void function. */
|
||||
char *f_body;
|
||||
size_t f_body_size; /* Size of body. Power of 2. */
|
||||
size_t f_code_size;
|
||||
bc_label_group *f_label;
|
||||
arg_list *f_params;
|
||||
arg_list *f_autos;
|
||||
} bc_function;
|
||||
|
||||
/* Code addresses. */
|
||||
typedef struct {
|
||||
unsigned int pc_func;
|
||||
unsigned int pc_addr;
|
||||
} program_counter;
|
||||
|
||||
|
||||
/* Variables are "pushable" (auto) and thus we need a stack mechanism.
|
||||
This is built into the variable record. */
|
||||
|
||||
typedef struct bc_var
|
||||
{
|
||||
bc_num v_value;
|
||||
struct bc_var *v_next;
|
||||
} bc_var;
|
||||
|
||||
|
||||
/* bc arrays can also be "auto" variables and thus need the same
|
||||
kind of stacking mechanisms. */
|
||||
|
||||
typedef struct bc_array_node
|
||||
{
|
||||
union
|
||||
{
|
||||
bc_num n_num [NODE_SIZE];
|
||||
struct bc_array_node *n_down [NODE_SIZE];
|
||||
} n_items;
|
||||
} bc_array_node;
|
||||
|
||||
typedef struct bc_array
|
||||
{
|
||||
bc_array_node *a_tree;
|
||||
short a_depth;
|
||||
} bc_array;
|
||||
|
||||
typedef struct bc_var_array
|
||||
{
|
||||
bc_array *a_value;
|
||||
char a_param;
|
||||
struct bc_var_array *a_next;
|
||||
} bc_var_array;
|
||||
|
||||
|
||||
/* For the stacks, execution and function, we need records to allow
|
||||
for arbitrary size. */
|
||||
|
||||
typedef struct estack_rec {
|
||||
bc_num s_num;
|
||||
struct estack_rec *s_next;
|
||||
} estack_rec;
|
||||
|
||||
typedef struct fstack_rec {
|
||||
int s_val;
|
||||
struct fstack_rec *s_next;
|
||||
} fstack_rec;
|
||||
|
||||
|
||||
/* The following are for the name tree. */
|
||||
|
||||
typedef struct id_rec {
|
||||
char *id; /* The program name. */
|
||||
/* A name == 0 => nothing assigned yet. */
|
||||
int a_name; /* The array variable name (number). */
|
||||
int f_name; /* The function name (number). */
|
||||
int v_name; /* The variable name (number). */
|
||||
short balance; /* For the balanced tree. */
|
||||
struct id_rec *left, *right; /* Tree pointers. */
|
||||
} id_rec;
|
||||
|
||||
|
||||
/* A list of files to process. */
|
||||
|
||||
typedef struct file_node {
|
||||
char *name;
|
||||
struct file_node *next;
|
||||
} file_node;
|
||||
|
||||
/* Macro Definitions */
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
#define HISTORY_SIZE(n) history(hist, &histev, H_SETSIZE, n)
|
||||
#define UNLIMIT_HISTORY history(hist, &histev, H_SETSIZE, INT_MAX)
|
||||
#endif
|
||||
|
||||
#if defined(READLINE)
|
||||
#define HISTORY_SIZE(n) stifle_history(n)
|
||||
#define UNLIMIT_HISTORY unstifle_history()
|
||||
#endif
|
||||
|
||||
/* Now the global variable declarations. */
|
||||
#include "global.h"
|
|
@ -0,0 +1,95 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* const.h: Constants for bc. */
|
||||
|
||||
/* 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 16777215 /* this should be NODE_SIZE^NODE_DEPTH-1 */
|
||||
|
||||
#define NODE_SIZE 64 /* Must be a power of 2. */
|
||||
#define NODE_MASK 0x3f /* Must be NODE_SIZE-1. */
|
||||
#define NODE_SHIFT 6 /* Number of 1 bits in NODE_MASK. */
|
||||
#define NODE_DEPTH 4
|
||||
|
||||
|
||||
/* Other BC limits defined but not part of POSIX. */
|
||||
|
||||
#define BC_LABEL_GROUP 64
|
||||
#define BC_LABEL_LOG 6
|
||||
#define BC_START_SIZE 1024 /* Initial code body size. */
|
||||
|
||||
/* Maximum number of variables, arrays and functions and the
|
||||
allocation increment for the dynamic arrays. */
|
||||
|
||||
#define MAX_STORE 32767
|
||||
#define STORE_INCR 32
|
||||
|
||||
/* Other interesting constants. */
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
/* for use with lookup (). */
|
||||
#define SIMPLE 0
|
||||
#define ARRAY 1
|
||||
#define FUNCT 2
|
||||
#define FUNCTDEF 3
|
||||
|
||||
#ifdef __STDC__
|
||||
#define CONST const
|
||||
#define VOID void
|
||||
#else
|
||||
#define CONST
|
||||
#define VOID
|
||||
#endif
|
|
@ -0,0 +1,795 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
/* execute.c - run a bc program. */
|
||||
|
||||
#include "bcdefs.h"
|
||||
#include <signal.h>
|
||||
#include "proto.h"
|
||||
|
||||
|
||||
/* The SIGINT interrupt handling routine. */
|
||||
|
||||
int had_sigint;
|
||||
|
||||
void
|
||||
stop_execution ( int sig )
|
||||
{
|
||||
had_sigint = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Get the current byte and advance the PC counter. */
|
||||
|
||||
unsigned char
|
||||
byte ( program_counter *p )
|
||||
{
|
||||
return (functions[p->pc_func].f_body[p->pc_addr++]);
|
||||
}
|
||||
|
||||
|
||||
/* The routine that actually runs the machine. */
|
||||
|
||||
void
|
||||
execute (void)
|
||||
{
|
||||
unsigned long label_num, l_gp, l_off;
|
||||
bc_label_group *gp;
|
||||
|
||||
char inst, ch;
|
||||
long new_func;
|
||||
long var_name;
|
||||
|
||||
long const_base;
|
||||
|
||||
bc_num temp_num;
|
||||
arg_list *auto_list;
|
||||
|
||||
/* Initialize this run... */
|
||||
pc.pc_func = 0;
|
||||
pc.pc_addr = 0;
|
||||
runtime_error = FALSE;
|
||||
bc_init_num (&temp_num);
|
||||
|
||||
/* Set up the interrupt mechanism for an interactive session. */
|
||||
if (interactive)
|
||||
{
|
||||
signal (SIGINT, stop_execution);
|
||||
}
|
||||
|
||||
had_sigint = FALSE;
|
||||
while (pc.pc_addr < functions[pc.pc_func].f_code_size
|
||||
&& !runtime_error && !had_sigint)
|
||||
{
|
||||
inst = byte(&pc);
|
||||
|
||||
#if DEBUG > 3
|
||||
{ /* Print out address and the stack before each instruction.*/
|
||||
int depth; estack_rec *temp = ex_stack;
|
||||
|
||||
printf ("func=%d addr=%d inst=%c\n",pc.pc_func, pc.pc_addr, inst);
|
||||
if (temp == NULL) printf ("empty stack.\n", inst);
|
||||
else
|
||||
{
|
||||
depth = 1;
|
||||
while (temp != NULL)
|
||||
{
|
||||
printf (" %d = ", depth);
|
||||
bc_out_num (temp->s_num, 10, out_char, std_only);
|
||||
depth++;
|
||||
temp = temp->s_next;
|
||||
}
|
||||
out_char ('\n');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch ( inst )
|
||||
{
|
||||
|
||||
case 'A' : /* increment array variable (Add one). */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
incr_array (var_name);
|
||||
break;
|
||||
|
||||
case 'B' : /* Branch to a label if TOS != 0. Remove value on TOS. */
|
||||
case 'Z' : /* Branch to a label if TOS == 0. Remove value on TOS. */
|
||||
c_code = !bc_is_zero (ex_stack->s_num);
|
||||
pop ();
|
||||
/*FALLTHROUGH*/ /* common branch and jump code */
|
||||
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;
|
||||
if (gp)
|
||||
pc.pc_addr = gp->l_adrs[l_off];
|
||||
else {
|
||||
rt_error ("Internal error.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'C' : /* Call a function. */
|
||||
/* Get the function number. */
|
||||
new_func = byte(&pc);
|
||||
if ((new_func & 0x80) != 0)
|
||||
new_func = ((new_func & 0x7f) << 8) + byte(&pc);
|
||||
|
||||
/* Check to make sure it is defined. */
|
||||
if (!functions[new_func].f_defined)
|
||||
{
|
||||
rt_error ("Function %s not defined.", f_names[new_func]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check and push parameters. */
|
||||
process_params (&pc, new_func);
|
||||
|
||||
/* Push auto variables. */
|
||||
for (auto_list = functions[new_func].f_autos;
|
||||
auto_list != NULL;
|
||||
auto_list = auto_list->next)
|
||||
auto_var (auto_list->av_name);
|
||||
|
||||
/* Push pc and ibase. */
|
||||
fpush (pc.pc_func);
|
||||
fpush (pc.pc_addr);
|
||||
fpush (i_base);
|
||||
|
||||
/* Reset pc to start of function. */
|
||||
pc.pc_func = new_func;
|
||||
pc.pc_addr = 0;
|
||||
break;
|
||||
|
||||
case 'D' : /* Duplicate top of stack */
|
||||
push_copy (ex_stack->s_num);
|
||||
break;
|
||||
|
||||
case 'K' : /* Push a constant */
|
||||
/* Get the input base and convert it to a bc number. */
|
||||
if (pc.pc_func == 0)
|
||||
const_base = i_base;
|
||||
else
|
||||
const_base = fn_stack->s_val;
|
||||
if (const_base == 10)
|
||||
push_b10_const (&pc);
|
||||
else
|
||||
push_constant (prog_char, const_base);
|
||||
break;
|
||||
|
||||
case 'L' : /* load array variable */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
load_array (var_name);
|
||||
break;
|
||||
|
||||
case 'M' : /* decrement array variable (Minus!) */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
decr_array (var_name);
|
||||
break;
|
||||
|
||||
case 'O' : /* Write a string to the output with processing. */
|
||||
while ((ch = byte(&pc)) != '"')
|
||||
if (ch != '\\')
|
||||
out_schar (ch);
|
||||
else
|
||||
{
|
||||
ch = byte(&pc);
|
||||
if (ch == '"') break;
|
||||
switch (ch)
|
||||
{
|
||||
case 'a': out_schar (007); break;
|
||||
case 'b': out_schar ('\b'); break;
|
||||
case 'f': out_schar ('\f'); break;
|
||||
case 'n': out_schar ('\n'); break;
|
||||
case 'q': out_schar ('"'); break;
|
||||
case 'r': out_schar ('\r'); break;
|
||||
case 't': out_schar ('\t'); break;
|
||||
case '\\': out_schar ('\\'); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
fflush (stdout);
|
||||
break;
|
||||
|
||||
case 'R' : /* Return from function */
|
||||
if (pc.pc_func != 0)
|
||||
{
|
||||
/* "Pop" autos and parameters. */
|
||||
pop_vars(functions[pc.pc_func].f_autos);
|
||||
pop_vars(functions[pc.pc_func].f_params);
|
||||
/* reset the pc. */
|
||||
fpop ();
|
||||
pc.pc_addr = fpop ();
|
||||
pc.pc_func = fpop ();
|
||||
}
|
||||
else
|
||||
rt_error ("Return from main program.");
|
||||
break;
|
||||
|
||||
case 'S' : /* store array variable */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f ) << 8) + byte(&pc);
|
||||
store_array (var_name);
|
||||
break;
|
||||
|
||||
case 'T' : /* Test tos for zero */
|
||||
c_code = bc_is_zero (ex_stack->s_num);
|
||||
assign (c_code);
|
||||
break;
|
||||
|
||||
case 'W' : /* Write the value on the top of the stack. */
|
||||
case 'P' : /* Write the value on the top of the stack. No newline. */
|
||||
bc_out_num (ex_stack->s_num, o_base, out_char, std_only);
|
||||
if (inst == 'W') out_char ('\n');
|
||||
store_var (4); /* Special variable "last". */
|
||||
fflush (stdout);
|
||||
pop ();
|
||||
break;
|
||||
|
||||
case 'c' : /* Call special function. */
|
||||
new_func = byte(&pc);
|
||||
|
||||
switch (new_func)
|
||||
{
|
||||
case 'L': /* Length function. */
|
||||
/* For the number 0.xxxx, 0 is not significant. */
|
||||
if (ex_stack->s_num->n_len == 1 &&
|
||||
ex_stack->s_num->n_scale != 0 &&
|
||||
ex_stack->s_num->n_value[0] == 0 )
|
||||
bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
|
||||
else
|
||||
bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_len
|
||||
+ ex_stack->s_num->n_scale);
|
||||
break;
|
||||
|
||||
case 'S': /* Scale function. */
|
||||
bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
|
||||
break;
|
||||
|
||||
case 'R': /* Square Root function. */
|
||||
if (!bc_sqrt (&ex_stack->s_num, scale))
|
||||
rt_error ("Square root of a negative number");
|
||||
break;
|
||||
|
||||
case 'I': /* Read function. */
|
||||
push_constant (input_char, i_base);
|
||||
break;
|
||||
|
||||
case 'X': /* Random function. */
|
||||
push_copy (_zero_);
|
||||
bc_int2num (&ex_stack->s_num, random());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd' : /* Decrement number */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
decr_var (var_name);
|
||||
break;
|
||||
|
||||
case 'h' : /* Halt the machine. */
|
||||
bc_exit (0);
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
|
||||
case 'i' : /* increment number */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
incr_var (var_name);
|
||||
break;
|
||||
|
||||
case 'l' : /* load variable */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
load_var (var_name);
|
||||
break;
|
||||
|
||||
case 'n' : /* Negate top of stack. */
|
||||
bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num, 0);
|
||||
break;
|
||||
|
||||
case 'p' : /* Pop the execution stack. */
|
||||
pop ();
|
||||
break;
|
||||
|
||||
case 's' : /* store variable */
|
||||
var_name = byte(&pc);
|
||||
if ((var_name & 0x80) != 0)
|
||||
var_name = ((var_name & 0x7f) << 8) + byte(&pc);
|
||||
store_var (var_name);
|
||||
break;
|
||||
|
||||
case 'w' : /* Write a string to the output. */
|
||||
while ((ch = byte(&pc)) != '"') out_schar (ch);
|
||||
fflush (stdout);
|
||||
break;
|
||||
|
||||
case 'x' : /* Exchange Top of Stack with the one under the tos. */
|
||||
if (check_stack(2)) {
|
||||
bc_num temp = ex_stack->s_num;
|
||||
ex_stack->s_num = ex_stack->s_next->s_num;
|
||||
ex_stack->s_next->s_num = temp;
|
||||
}
|
||||
break;
|
||||
|
||||
case '0' : /* Load Constant 0. */
|
||||
push_copy (_zero_);
|
||||
break;
|
||||
|
||||
case '1' : /* Load Constant 1. */
|
||||
push_copy (_one_);
|
||||
break;
|
||||
|
||||
case '!' : /* Negate the boolean value on top of the stack. */
|
||||
c_code = bc_is_zero (ex_stack->s_num);
|
||||
assign (c_code);
|
||||
break;
|
||||
|
||||
case '&' : /* compare greater than */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = !bc_is_zero (ex_stack->s_next->s_num)
|
||||
&& !bc_is_zero (ex_stack->s_num);
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '|' : /* compare greater than */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = !bc_is_zero (ex_stack->s_next->s_num)
|
||||
|| !bc_is_zero (ex_stack->s_num);
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '+' : /* add */
|
||||
if (check_stack(2))
|
||||
{
|
||||
bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
|
||||
pop();
|
||||
pop();
|
||||
push_num (temp_num);
|
||||
bc_init_num (&temp_num);
|
||||
}
|
||||
break;
|
||||
|
||||
case '-' : /* subtract */
|
||||
if (check_stack(2))
|
||||
{
|
||||
bc_sub (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
|
||||
pop();
|
||||
pop();
|
||||
push_num (temp_num);
|
||||
bc_init_num (&temp_num);
|
||||
}
|
||||
break;
|
||||
|
||||
case '*' : /* multiply */
|
||||
if (check_stack(2))
|
||||
{
|
||||
bc_multiply (ex_stack->s_next->s_num, ex_stack->s_num,
|
||||
&temp_num, scale);
|
||||
pop();
|
||||
pop();
|
||||
push_num (temp_num);
|
||||
bc_init_num (&temp_num);
|
||||
}
|
||||
break;
|
||||
|
||||
case '/' : /* divide */
|
||||
if (check_stack(2))
|
||||
{
|
||||
if (bc_divide (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num, &temp_num, scale) == 0)
|
||||
{
|
||||
pop();
|
||||
pop();
|
||||
push_num (temp_num);
|
||||
bc_init_num (&temp_num);
|
||||
}
|
||||
else
|
||||
rt_error ("Divide by zero");
|
||||
}
|
||||
break;
|
||||
|
||||
case '%' : /* remainder */
|
||||
if (check_stack(2))
|
||||
{
|
||||
if (bc_is_zero (ex_stack->s_num))
|
||||
rt_error ("Modulo by zero");
|
||||
else
|
||||
{
|
||||
bc_modulo (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num, &temp_num, scale);
|
||||
pop();
|
||||
pop();
|
||||
push_num (temp_num);
|
||||
bc_init_num (&temp_num);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '^' : /* raise */
|
||||
if (check_stack(2))
|
||||
{
|
||||
bc_raise (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num, &temp_num, scale);
|
||||
if (bc_is_zero (ex_stack->s_next->s_num) && bc_is_neg (ex_stack->s_num))
|
||||
rt_error ("divide by zero");
|
||||
pop();
|
||||
pop();
|
||||
push_num (temp_num);
|
||||
bc_init_num (&temp_num);
|
||||
}
|
||||
break;
|
||||
|
||||
case '=' : /* compare equal */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = bc_compare (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num) == 0;
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '#' : /* compare not equal */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = bc_compare (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num) != 0;
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '<' : /* compare less than */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = bc_compare (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num) == -1;
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '{' : /* compare less than or equal */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = bc_compare (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num) <= 0;
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '>' : /* compare greater than */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = bc_compare (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num) == 1;
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
case '}' : /* compare greater than or equal */
|
||||
if (check_stack(2))
|
||||
{
|
||||
c_code = bc_compare (ex_stack->s_next->s_num,
|
||||
ex_stack->s_num) >= 0;
|
||||
pop ();
|
||||
assign (c_code);
|
||||
}
|
||||
break;
|
||||
|
||||
default : /* error! */
|
||||
rt_error ("bad instruction: inst=%c", inst);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up the function stack and pop all autos/parameters. */
|
||||
while (pc.pc_func != 0)
|
||||
{
|
||||
pop_vars(functions[pc.pc_func].f_autos);
|
||||
pop_vars(functions[pc.pc_func].f_params);
|
||||
fpop ();
|
||||
pc.pc_addr = fpop ();
|
||||
pc.pc_func = fpop ();
|
||||
}
|
||||
|
||||
/* Clean up the execution stack. */
|
||||
while (ex_stack != NULL) pop();
|
||||
|
||||
/* Clean up the interrupt stuff. */
|
||||
if (interactive)
|
||||
{
|
||||
signal (SIGINT, use_quit);
|
||||
if (had_sigint)
|
||||
printf ("\ninterrupted execution.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Prog_char gets another byte from the program. It is used for
|
||||
conversion of text constants in the code to numbers. */
|
||||
|
||||
int
|
||||
prog_char (void)
|
||||
{
|
||||
return (int) byte(&pc);
|
||||
}
|
||||
|
||||
|
||||
/* Read a character from the standard input. This function is used
|
||||
by the "read" function. */
|
||||
|
||||
int
|
||||
input_char (void)
|
||||
{
|
||||
int 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();
|
||||
out_col = 0; /* Saw a new line */
|
||||
}
|
||||
}
|
||||
|
||||
/* Classify and preprocess the input character. */
|
||||
if (isdigit(in_ch))
|
||||
return (in_ch - '0');
|
||||
if (in_ch >= 'A' && in_ch <= 'Z')
|
||||
return (in_ch + 10 - 'A');
|
||||
if (in_ch >= 'a' && in_ch <= 'z')
|
||||
return (in_ch + 10 - 'a');
|
||||
if (in_ch == '.' || in_ch == '+' || in_ch == '-')
|
||||
return (in_ch);
|
||||
if (in_ch == '~')
|
||||
return (':');
|
||||
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 (int (*in_char)(VOID), int conv_base)
|
||||
{
|
||||
int digits;
|
||||
bc_num build, temp, result, mult, divisor;
|
||||
int in_ch, first_ch;
|
||||
char negative;
|
||||
|
||||
/* Initialize all bc numbers */
|
||||
bc_init_num (&temp);
|
||||
bc_init_num (&result);
|
||||
bc_init_num (&mult);
|
||||
build = bc_copy_num (_zero_);
|
||||
negative = FALSE;
|
||||
|
||||
/* The conversion base. */
|
||||
bc_int2num (&mult, conv_base);
|
||||
|
||||
/* Get things ready. */
|
||||
in_ch = in_char();
|
||||
/* ~ is space returned by input_char(), prog_char does not return spaces. */
|
||||
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 < 36)
|
||||
{
|
||||
first_ch = in_ch;
|
||||
in_ch = in_char();
|
||||
if (in_ch < 36 && first_ch >= conv_base)
|
||||
first_ch = conv_base - 1;
|
||||
bc_int2num (&build, (int) first_ch);
|
||||
}
|
||||
|
||||
/* Convert the integer part. */
|
||||
while (in_ch < 36)
|
||||
{
|
||||
if (in_ch < 36 && in_ch >= conv_base) in_ch = conv_base-1;
|
||||
bc_multiply (build, mult, &result, 0);
|
||||
bc_int2num (&temp, (int) in_ch);
|
||||
bc_add (result, temp, &build, 0);
|
||||
in_ch = in_char();
|
||||
}
|
||||
if (in_ch == '.')
|
||||
{
|
||||
in_ch = in_char();
|
||||
if (in_ch >= conv_base) in_ch = conv_base-1;
|
||||
bc_free_num (&result);
|
||||
bc_free_num (&temp);
|
||||
divisor = bc_copy_num (_one_);
|
||||
result = bc_copy_num (_zero_);
|
||||
digits = 0;
|
||||
while (in_ch < 36)
|
||||
{
|
||||
bc_multiply (result, mult, &result, 0);
|
||||
bc_int2num (&temp, (int) in_ch);
|
||||
bc_add (result, temp, &result, 0);
|
||||
bc_multiply (divisor, mult, &divisor, 0);
|
||||
digits++;
|
||||
in_ch = in_char();
|
||||
if (in_ch < 36 && in_ch >= conv_base) in_ch = conv_base-1;
|
||||
}
|
||||
bc_divide (result, divisor, &result, digits);
|
||||
bc_add (build, result, &build, 0);
|
||||
}
|
||||
|
||||
/* Final work. */
|
||||
if (negative)
|
||||
bc_sub (_zero_, build, &build, 0);
|
||||
|
||||
push_num (build);
|
||||
bc_free_num (&temp);
|
||||
bc_free_num (&result);
|
||||
bc_free_num (&mult);
|
||||
}
|
||||
|
||||
|
||||
/* When converting base 10 constants from the program, we use this
|
||||
more efficient way to convert them to numbers. PC tells where
|
||||
the constant starts and is expected to be advanced to after
|
||||
the constant. */
|
||||
|
||||
void
|
||||
push_b10_const (program_counter *progctr)
|
||||
{
|
||||
bc_num build;
|
||||
program_counter look_pc;
|
||||
int kdigits, kscale;
|
||||
unsigned char inchar;
|
||||
char *ptr;
|
||||
|
||||
/* Count the digits and get things ready. */
|
||||
look_pc = *progctr;
|
||||
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 progctr. */
|
||||
inchar = byte(progctr);
|
||||
|
||||
/* Secial cases of 0, 1, and A-F single inputs. */
|
||||
if (kdigits == 1 && kscale == 0)
|
||||
{
|
||||
if (inchar == 0)
|
||||
{
|
||||
push_copy (_zero_);
|
||||
inchar = byte(progctr);
|
||||
return;
|
||||
}
|
||||
if (inchar == 1) {
|
||||
push_copy (_one_);
|
||||
inchar = byte(progctr);
|
||||
return;
|
||||
}
|
||||
if (inchar > 9)
|
||||
{
|
||||
bc_init_num (&build);
|
||||
bc_int2num (&build, inchar);
|
||||
push_num (build);
|
||||
inchar = byte(progctr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the new number. */
|
||||
if (kdigits == 0)
|
||||
{
|
||||
build = bc_new_num (1,kscale);
|
||||
ptr = build->n_value;
|
||||
*ptr++ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
build = bc_new_num (kdigits,kscale);
|
||||
ptr = build->n_value;
|
||||
}
|
||||
|
||||
while (inchar != ':')
|
||||
{
|
||||
if (inchar != '.')
|
||||
{
|
||||
if (inchar > 9)
|
||||
*ptr++ = 9;
|
||||
else
|
||||
*ptr++ = inchar;
|
||||
}
|
||||
inchar = byte(progctr);
|
||||
}
|
||||
push_num (build);
|
||||
}
|
||||
|
||||
|
||||
/* Put the correct value on the stack for C_CODE. Frees TOS num. */
|
||||
|
||||
void
|
||||
assign (char code)
|
||||
{
|
||||
bc_free_num (&ex_stack->s_num);
|
||||
if (code)
|
||||
ex_stack->s_num = bc_copy_num (_one_);
|
||||
else
|
||||
ex_stack->s_num = bc_copy_num (_zero_);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
ed libmath.h <<EOS-EOS
|
||||
1,1s/^/{"/
|
||||
1,\$s/\$/",/
|
||||
2,\$s/^/"/
|
||||
\$,\$d
|
||||
\$,\$s/,\$/,0}/
|
||||
w
|
||||
q
|
||||
EOS-EOS
|
|
@ -0,0 +1,38 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* global.c: This defines the global variables. */
|
||||
|
||||
/* We are global.c ... so define and initialize variables here. */
|
||||
|
||||
#define _GLOBAL_C
|
||||
|
||||
#include "bcdefs.h"
|
||||
|
||||
CONST char *libmath[] =
|
||||
#include "libmath.h"
|
||||
;
|
|
@ -0,0 +1,156 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* global.h: The global variables for bc. */
|
||||
|
||||
/* The current break level's label. */
|
||||
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 INIT(NULL);
|
||||
EXTERN int genlen INIT(0);
|
||||
|
||||
/* 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 INIT(FALSE);
|
||||
|
||||
/* Just generate the byte code. -c flag. */
|
||||
EXTERN int compile_only INIT(FALSE);
|
||||
|
||||
/* Load the standard math functions. -l flag. */
|
||||
EXTERN int use_math INIT(FALSE);
|
||||
|
||||
/* Give a warning on use of any non-standard feature (non-POSIX). -w flag. */
|
||||
EXTERN int warn_not_std INIT(FALSE);
|
||||
|
||||
/* Accept POSIX bc only! -s flag. */
|
||||
EXTERN int std_only INIT(FALSE);
|
||||
|
||||
/* Don't print the banner at start up. -q flag. */
|
||||
EXTERN int quiet INIT(FALSE);
|
||||
|
||||
/* The list of file names to process. */
|
||||
EXTERN file_node *file_names INIT(NULL);
|
||||
|
||||
/* The name of the current file being processed. */
|
||||
EXTERN char *file_name;
|
||||
|
||||
/* Is the current file a named file or standard input? */
|
||||
EXTERN char is_std_in;
|
||||
|
||||
/* global variables for the bc machine. All will be dynamic in size.*/
|
||||
/* Function storage. main is (0) and functions (1-f_count) */
|
||||
|
||||
EXTERN bc_function *functions;
|
||||
EXTERN char **f_names;
|
||||
EXTERN int f_count;
|
||||
|
||||
/* Variable stoarge and reverse names. */
|
||||
|
||||
EXTERN bc_var **variables;
|
||||
EXTERN char **v_names;
|
||||
EXTERN int v_count;
|
||||
|
||||
/* Array Variable storage and reverse names. */
|
||||
|
||||
EXTERN bc_var_array **arrays;
|
||||
EXTERN char **a_names;
|
||||
EXTERN int a_count;
|
||||
|
||||
/* Execution stack. */
|
||||
EXTERN estack_rec *ex_stack;
|
||||
|
||||
/* Function return stack. */
|
||||
EXTERN fstack_rec *fn_stack;
|
||||
|
||||
/* Current ibase, obase, scale, and n_history (if needed). */
|
||||
EXTERN int i_base;
|
||||
EXTERN int o_base;
|
||||
EXTERN int scale;
|
||||
#if defined(READLINE) || defined(LIBEDIT)
|
||||
EXTERN int n_history;
|
||||
#endif
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
/* LIBEDIT data */
|
||||
EditLine *edit INIT(NULL);
|
||||
History *hist;
|
||||
HistEvent histev;
|
||||
#endif
|
||||
|
||||
/* "Condition code" -- false (0) or true (1) */
|
||||
EXTERN char c_code;
|
||||
|
||||
/* Records the number of the runtime error. */
|
||||
EXTERN char runtime_error;
|
||||
|
||||
/* Holds the current location of execution. */
|
||||
EXTERN program_counter pc;
|
||||
|
||||
/* For POSIX bc, this is just for number output, not strings. */
|
||||
EXTERN int out_col;
|
||||
|
||||
/* Keeps track of the current number of characters per output line.
|
||||
This includes the \n at the end of the line. */
|
||||
EXTERN int line_size;
|
||||
|
||||
/* Input Line numbers and other error information. */
|
||||
EXTERN int line_no;
|
||||
EXTERN int had_error;
|
||||
|
||||
/* For larger identifiers, a tree, and how many "storage" locations
|
||||
have been allocated. */
|
||||
|
||||
EXTERN int next_array;
|
||||
EXTERN int next_func;
|
||||
EXTERN int next_var;
|
||||
|
||||
EXTERN id_rec *name_tree;
|
||||
|
||||
/* For use with getopt. Do not declare them here.*/
|
||||
extern int optind;
|
||||
|
||||
/* Access to the yy input file. Defined in scan.c. */
|
||||
extern FILE *yyin;
|
||||
|
||||
/* Access to libmath */
|
||||
extern CONST char *libmath[];
|
|
@ -0,0 +1,336 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* libmath.b for bc. */
|
||||
|
||||
scale = 20
|
||||
|
||||
/* Uses the fact that e^x = (e^(x/2))^2
|
||||
When x is small enough, we use the series:
|
||||
e^x = 1 + x + x^2/2! + x^3/3! + ...
|
||||
*/
|
||||
|
||||
define e(x) {
|
||||
auto a, b, 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. */
|
||||
/* b - holds the original ibase. */
|
||||
|
||||
/* Non base 10 ibase? */
|
||||
if (ibase != A) {
|
||||
b = ibase;
|
||||
ibase = A;
|
||||
v = e(x);
|
||||
ibase = b;
|
||||
return (v);
|
||||
}
|
||||
|
||||
/* 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 b, e, f, i, m, n, v, z
|
||||
|
||||
/* Non base 10 ibase? */
|
||||
if (ibase != A) {
|
||||
b = ibase;
|
||||
ibase = A;
|
||||
v = l(x);
|
||||
ibase = b;
|
||||
return (v);
|
||||
}
|
||||
|
||||
/* 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 b, e, i, m, n, s, v, z
|
||||
|
||||
/* Non base 10 ibase? */
|
||||
if (ibase != A) {
|
||||
b = ibase;
|
||||
ibase = A;
|
||||
v = s(x);
|
||||
ibase = b;
|
||||
return (v);
|
||||
}
|
||||
|
||||
/* 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 b, v, z;
|
||||
|
||||
/* Non base 10 ibase? */
|
||||
if (ibase != A) {
|
||||
b = ibase;
|
||||
ibase = A;
|
||||
v = c(x);
|
||||
ibase = b;
|
||||
return (v);
|
||||
}
|
||||
|
||||
z = scale;
|
||||
scale = scale*1.2;
|
||||
v = s(x+a(1)*2);
|
||||
scale = z;
|
||||
return (v/1);
|
||||
}
|
||||
|
||||
/* Arctan: Using the formula:
|
||||
atan(x) = atan(c) + atan((x-c)/(1+xc)) for a small c (.2 here)
|
||||
For under .2, use the series:
|
||||
atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ... */
|
||||
|
||||
define a(x) {
|
||||
auto a, b, 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. */
|
||||
|
||||
/* Non base 10 ibase? */
|
||||
if (ibase != A) {
|
||||
b = ibase;
|
||||
ibase = A;
|
||||
v = a(x);
|
||||
ibase = b;
|
||||
return (v);
|
||||
}
|
||||
|
||||
/* Negative x? */
|
||||
m = 1;
|
||||
if (x<0) {
|
||||
m = -1;
|
||||
x = -x;
|
||||
}
|
||||
|
||||
/* Special case and for fast answers */
|
||||
if (x==1) {
|
||||
if (scale <= 25) return (.7853981633974483096156608/m)
|
||||
if (scale <= 40) return (.7853981633974483096156608458198757210492/m)
|
||||
if (scale <= 60) \
|
||||
return (.785398163397448309615660845819875721049292349843776455243736/m)
|
||||
}
|
||||
if (x==.2) {
|
||||
if (scale <= 25) return (.1973955598498807583700497/m)
|
||||
if (scale <= 40) return (.1973955598498807583700497651947902934475/m)
|
||||
if (scale <= 60) \
|
||||
return (.197395559849880758370049765194790293447585103787852101517688/m)
|
||||
}
|
||||
|
||||
|
||||
/* Save the scale. */
|
||||
z = scale;
|
||||
|
||||
/* Note: a and f are known to be zero due to being auto vars. */
|
||||
/* Calculate atan of a known number. */
|
||||
if (x > .2) {
|
||||
scale = z+5;
|
||||
a = a(.2);
|
||||
}
|
||||
|
||||
/* Precondition x. */
|
||||
scale = z+3;
|
||||
while (x > .2) {
|
||||
f += 1;
|
||||
x = (x-.2) / (1+x*.2);
|
||||
}
|
||||
|
||||
/* Initialize the series. */
|
||||
v = n = x;
|
||||
s = -x*x;
|
||||
|
||||
/* Calculate the series. */
|
||||
for (i=3; 1; i+=2) {
|
||||
e = (n *= s) / i;
|
||||
if (e == 0) {
|
||||
scale = z;
|
||||
return ((f*a+v)/m);
|
||||
}
|
||||
v += e
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Bessel function of integer order. Uses the following:
|
||||
j(-n,x) = (-1)^n*j(n,x)
|
||||
j(n,x) = x^n/(2^n*n!) * (1 - x^2/(2^2*1!*(n+1)) + x^4/(2^4*2!*(n+1)*(n+2))
|
||||
- x^6/(2^6*3!*(n+1)*(n+2)*(n+3)) .... )
|
||||
*/
|
||||
define j(n,x) {
|
||||
auto a, b, d, e, f, i, m, s, v, z
|
||||
|
||||
/* Non base 10 ibase? */
|
||||
if (ibase != A) {
|
||||
b = ibase;
|
||||
ibase = A;
|
||||
v = j(n,x);
|
||||
ibase = b;
|
||||
return (v);
|
||||
}
|
||||
|
||||
/* 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 + length(f) - scale(f);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,353 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* load.c: This code "loads" code into the code segments. */
|
||||
|
||||
#include "bcdefs.h"
|
||||
#include "proto.h"
|
||||
|
||||
/* Load variables. */
|
||||
|
||||
program_counter load_adr;
|
||||
char load_str;
|
||||
char load_const;
|
||||
|
||||
/* Initialize the load sequence. */
|
||||
void
|
||||
init_load (void)
|
||||
{
|
||||
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 (unsigned char thebyte)
|
||||
{
|
||||
unsigned long prog_addr;
|
||||
bc_function *f;
|
||||
char *new_body;
|
||||
|
||||
/* If there was an error, don't continue. */
|
||||
if (had_error) return;
|
||||
|
||||
/* Calculate the segment and offset. */
|
||||
prog_addr = load_adr.pc_addr++;
|
||||
f = &functions[load_adr.pc_func];
|
||||
|
||||
if (prog_addr >= f->f_body_size)
|
||||
{
|
||||
f->f_body_size *= 2;
|
||||
new_body = bc_malloc (f->f_body_size);
|
||||
memcpy(new_body, f->f_body, f->f_body_size/2);
|
||||
free (f->f_body);
|
||||
f->f_body = new_body;
|
||||
}
|
||||
|
||||
/* Store the thebyte. */
|
||||
f->f_body[prog_addr] = (char) (thebyte & 0xff);
|
||||
f->f_code_size++;
|
||||
}
|
||||
|
||||
|
||||
/* Define a label LAB to be the current program counter. */
|
||||
|
||||
void
|
||||
def_label (unsigned long lab)
|
||||
{
|
||||
bc_label_group *temp;
|
||||
unsigned long 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_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_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 (const char **str)
|
||||
{ int val = 0;
|
||||
char neg = FALSE;
|
||||
|
||||
if (**str == '-')
|
||||
{
|
||||
neg = TRUE;
|
||||
(*str)++;
|
||||
}
|
||||
while (isdigit((int)(**str)))
|
||||
val = val*10 + *(*str)++ - '0';
|
||||
|
||||
if (neg)
|
||||
return -val;
|
||||
else
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/* load_code loads the CODE into the machine. */
|
||||
|
||||
void
|
||||
load_code (const char *code)
|
||||
{
|
||||
const char *str;
|
||||
unsigned long ap_name; /* auto or parameter name. */
|
||||
unsigned long label_no;
|
||||
unsigned long vaf_name; /* variable, array or function number. */
|
||||
unsigned long func;
|
||||
static 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 > 'F' && (warn_not_std || std_only))
|
||||
{
|
||||
if (std_only)
|
||||
yyerror ("Error in numeric constant");
|
||||
else
|
||||
ct_warn ("Non-standard base in numeric constant");
|
||||
}
|
||||
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");
|
||||
bc_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++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,358 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* main.c: The main program for bc. */
|
||||
|
||||
#include "bcdefs.h"
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include "proto.h"
|
||||
#include "getopt.h"
|
||||
|
||||
|
||||
/* Variables for processing multiple files. */
|
||||
static char first_file;
|
||||
|
||||
/* Points to the last node in the file name list for easy adding. */
|
||||
static file_node *last = NULL;
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
/* The prompt for libedit. */
|
||||
char el_pmtchars[] = "";
|
||||
static char *el_pmtfunc(void);
|
||||
static char *el_pmtfunc(void) { return el_pmtchars; }
|
||||
#endif
|
||||
|
||||
/* long option support */
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"compile", 0, &compile_only, TRUE},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"interactive", 0, 0, 'i'},
|
||||
{"mathlib", 0, &use_math, TRUE},
|
||||
{"quiet", 0, &quiet, TRUE},
|
||||
{"standard", 0, &std_only, TRUE},
|
||||
{"version", 0, 0, 'v'},
|
||||
{"warn", 0, &warn_not_std, TRUE},
|
||||
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
usage (const char *progname)
|
||||
{
|
||||
printf ("usage: %s [options] [file ...]\n%s%s%s%s%s%s%s", progname,
|
||||
" -h --help print this usage and exit\n",
|
||||
" -i --interactive force interactive mode\n",
|
||||
" -l --mathlib use the predefined math routines\n",
|
||||
" -q --quiet don't print initial banner\n",
|
||||
" -s --standard non-standard bc constructs are errors\n",
|
||||
" -w --warn warn about non-standard bc constructs\n",
|
||||
" -v --version print version information and exit\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_args (int argc, char **argv)
|
||||
{
|
||||
int optch;
|
||||
int long_index;
|
||||
file_node *temp;
|
||||
|
||||
/* Force getopt to initialize. Depends on GNU getopt. */
|
||||
optind = 0;
|
||||
|
||||
/* Parse the command line */
|
||||
while (1)
|
||||
{
|
||||
optch = getopt_long (argc, argv, "chilqswv", long_options, &long_index);
|
||||
|
||||
if (optch == EOF) /* End of arguments. */
|
||||
break;
|
||||
|
||||
switch (optch)
|
||||
{
|
||||
case 0: /* Long option setting a var. */
|
||||
break;
|
||||
|
||||
case 'c': /* compile only */
|
||||
compile_only = TRUE;
|
||||
break;
|
||||
|
||||
case 'h': /* help */
|
||||
usage(argv[0]);
|
||||
bc_exit (0);
|
||||
break;
|
||||
|
||||
case 'i': /* force interactive */
|
||||
interactive = TRUE;
|
||||
break;
|
||||
|
||||
case 'l': /* math lib */
|
||||
use_math = TRUE;
|
||||
break;
|
||||
|
||||
case 'q': /* quiet mode */
|
||||
quiet = TRUE;
|
||||
break;
|
||||
|
||||
case 's': /* Non standard features give errors. */
|
||||
std_only = TRUE;
|
||||
break;
|
||||
|
||||
case 'v': /* Print the version. */
|
||||
show_bc_version ();
|
||||
bc_exit (0);
|
||||
break;
|
||||
|
||||
case 'w': /* Non standard features give warnings. */
|
||||
warn_not_std = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(argv[0]);
|
||||
bc_exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef QUIET
|
||||
quiet = TRUE;
|
||||
#endif
|
||||
|
||||
/* Add file names to a list of files to process. */
|
||||
while (optind < argc)
|
||||
{
|
||||
temp = 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 (int argc, char **argv)
|
||||
{
|
||||
char *env_value;
|
||||
char *env_argv[30];
|
||||
int env_argc;
|
||||
|
||||
/* Interactive? */
|
||||
if (isatty(0) && isatty(1))
|
||||
interactive = TRUE;
|
||||
|
||||
#ifdef HAVE_SETVBUF
|
||||
/* attempt to simplify interaction with applications such as emacs */
|
||||
(void) setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
#endif
|
||||
|
||||
/* Environment arguments. */
|
||||
env_value = getenv ("BC_ENV_ARGS");
|
||||
if (env_value != NULL)
|
||||
{
|
||||
env_argc = 1;
|
||||
env_argv[0] = strdup("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 < 3 && line_size != 0)
|
||||
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 ())
|
||||
bc_exit (1);
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
if (interactive) {
|
||||
/* Enable libedit support. */
|
||||
edit = el_init ("bc", stdin, stdout, stderr);
|
||||
hist = history_init();
|
||||
el_set (edit, EL_EDITOR, "emacs");
|
||||
el_set (edit, EL_HIST, history, hist);
|
||||
el_set (edit, EL_PROMPT, el_pmtfunc);
|
||||
el_source (edit, NULL);
|
||||
history (hist, &histev, H_SETSIZE, INT_MAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(READLINE)
|
||||
if (interactive) {
|
||||
/* Readline support. Set both application name and input file. */
|
||||
rl_readline_name = "bc";
|
||||
rl_instream = stdin;
|
||||
using_history ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do the parse. */
|
||||
yyparse ();
|
||||
|
||||
/* End the compile only output with a newline. */
|
||||
if (compile_only)
|
||||
printf ("\n");
|
||||
|
||||
bc_exit (0);
|
||||
return 0; // to keep the compiler from complaining
|
||||
}
|
||||
|
||||
|
||||
/* 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 (void)
|
||||
{
|
||||
FILE *new_file;
|
||||
file_node *temp;
|
||||
|
||||
/* Set the line number. */
|
||||
line_no = 1;
|
||||
|
||||
/* Check to see if we are done. */
|
||||
if (is_std_in) return (FALSE);
|
||||
|
||||
/* Open the other files. */
|
||||
if (use_math && first_file)
|
||||
{
|
||||
/* Load the code from a precompiled version of the math libarary. */
|
||||
CONST char **mstr;
|
||||
|
||||
/* 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"! */
|
||||
(void) lookup (strdup("e"), FUNCT);
|
||||
(void) lookup (strdup("l"), FUNCT);
|
||||
(void) lookup (strdup("s"), FUNCT);
|
||||
(void) lookup (strdup("a"), FUNCT);
|
||||
(void) lookup (strdup("c"), FUNCT);
|
||||
(void) lookup (strdup("j"), FUNCT);
|
||||
mstr = libmath;
|
||||
while (*mstr) {
|
||||
load_code (*mstr);
|
||||
mstr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* One of the argv values. */
|
||||
if (file_names != NULL)
|
||||
{
|
||||
new_file = fopen (file_names->name, "r");
|
||||
if (new_file != NULL)
|
||||
{
|
||||
new_yy_file (new_file);
|
||||
temp = file_names;
|
||||
file_name = temp->name;
|
||||
file_names = temp->next;
|
||||
free (temp);
|
||||
return TRUE;
|
||||
}
|
||||
fprintf (stderr, "File %s is unavailable.\n", file_names->name);
|
||||
bc_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)
|
||||
{
|
||||
if (!first_file) fclose (yyin);
|
||||
yyin = file;
|
||||
first_file = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Message to use quit. */
|
||||
|
||||
void
|
||||
use_quit (int sig)
|
||||
{
|
||||
#ifdef DONTEXIT
|
||||
int save = errno;
|
||||
write (1, "\n(interrupt) use quit to exit.\n", 31);
|
||||
signal (SIGINT, use_quit);
|
||||
errno = save;
|
||||
#else
|
||||
write (1, "\n(interrupt) Exiting bc.\n", 26);
|
||||
bc_exit(0);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* proto.h: Prototype function definitions for "external" functions. */
|
||||
|
||||
/* 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
|
||||
|
||||
/* From execute.c */
|
||||
void stop_execution (int);
|
||||
unsigned char byte (program_counter *pc_);
|
||||
void execute (void);
|
||||
int prog_char (void);
|
||||
int input_char (void);
|
||||
void push_constant (int (*in_char)(void), int conv_base);
|
||||
void push_b10_const (program_counter *pc_);
|
||||
void assign (char code);
|
||||
|
||||
/* From util.c */
|
||||
char *strcopyof (const char *str);
|
||||
arg_list *nextarg (arg_list *args, int val, int is_var);
|
||||
char *arg_str (arg_list *args);
|
||||
char *call_str (arg_list *args);
|
||||
void free_args (arg_list *args);
|
||||
void check_params (arg_list *params, arg_list *autos);
|
||||
void set_genstr_size (int);
|
||||
void init_gen (void);
|
||||
void generate (const char *str);
|
||||
void run_code (void);
|
||||
void out_char (int ch);
|
||||
void out_schar (int ch);
|
||||
id_rec *find_id (id_rec *tree, const char *id);
|
||||
int insert_id_rec (id_rec **root, id_rec *new_id);
|
||||
void init_tree (void);
|
||||
int lookup (char *name, int namekind);
|
||||
void *bc_malloc (size_t);
|
||||
void out_of_memory (void);
|
||||
void welcome (void);
|
||||
void warranty (const char *);
|
||||
void show_bc_version (void);
|
||||
void limits (void);
|
||||
void yyerror (const char *str ,...);
|
||||
void ct_warn (const char *mesg ,...);
|
||||
void rt_error (const char *mesg ,...);
|
||||
void rt_warn (const char *mesg ,...);
|
||||
void bc_exit (int);
|
||||
|
||||
/* From load.c */
|
||||
void init_load (void);
|
||||
void addbyte (unsigned char thebyte);
|
||||
void def_label (unsigned long lab);
|
||||
long long_val (const char **str);
|
||||
void load_code (const char *code);
|
||||
|
||||
/* From main.c */
|
||||
int open_new_file (void);
|
||||
void new_yy_file (FILE *file);
|
||||
void use_quit (int);
|
||||
|
||||
/* From storage.c */
|
||||
void init_storage (void);
|
||||
void more_functions (void);
|
||||
void more_variables (void);
|
||||
void more_arrays (void);
|
||||
void clear_func (int func);
|
||||
int fpop (void);
|
||||
void fpush (int val);
|
||||
void pop (void);
|
||||
void push_copy (bc_num num);
|
||||
void push_num (bc_num num);
|
||||
char check_stack (int depth);
|
||||
bc_var *get_var (int var_name);
|
||||
bc_num *get_array_num (int var_index, unsigned long _index_);
|
||||
void store_var (int var_name);
|
||||
void store_array (int var_name);
|
||||
void load_var (int var_name);
|
||||
void load_array (int var_name);
|
||||
void decr_var (int var_name);
|
||||
void decr_array (int var_name);
|
||||
void incr_var (int var_name);
|
||||
void incr_array (int var_name);
|
||||
void auto_var (int name);
|
||||
void free_a_tree (bc_array_node *root, int depth);
|
||||
void pop_vars (arg_list *list);
|
||||
void process_params (program_counter *_pc_, int func);
|
||||
|
||||
/* For the scanner and parser.... */
|
||||
int yyparse (void);
|
||||
int yylex (void);
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
/* The *?*&^ prompt function */
|
||||
char *null_prompt (EditLine *);
|
||||
#endif
|
||||
|
||||
/* Other things... */
|
||||
#ifndef HAVE_UNISTD_H
|
||||
(int getopt (int, char *[], CONST char *);
|
||||
#endif
|
|
@ -0,0 +1,454 @@
|
|||
%{
|
||||
/* sbc.y: A POSIX bc processor written for minix with no extensions. */
|
||||
|
||||
/* This file is part of GNU bc.
|
||||
Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License , or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
The Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor
|
||||
Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "bcdefs.h"
|
||||
#include "global.h" /* To get the global variables. */
|
||||
#include "proto.h"
|
||||
%}
|
||||
|
||||
%start program
|
||||
|
||||
%union {
|
||||
char *s_value;
|
||||
char c_value;
|
||||
int i_value;
|
||||
arg_list *a_value;
|
||||
}
|
||||
|
||||
%token <i_value> ENDOFLINE AND OR NOT
|
||||
%token <s_value> STRING NAME NUMBER
|
||||
/* '-', '+' are tokens themselves */
|
||||
%token <c_value> ASSIGN_OP
|
||||
/* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
|
||||
%token <s_value> REL_OP
|
||||
/* '==', '<=', '>=', '!=', '<', '>' */
|
||||
%token <c_value> INCR_DECR
|
||||
/* '++', '--' */
|
||||
%token <i_value> Define Break Quit Length
|
||||
/* 'define', 'break', 'quit', 'length' */
|
||||
%token <i_value> Return For If While Sqrt Else
|
||||
/* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
|
||||
%token <i_value> Scale Ibase Obase Auto Read
|
||||
/* 'scale', 'ibase', 'obase', 'auto', 'read' */
|
||||
%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
|
||||
/* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
|
||||
|
||||
/* The types of all other non-terminals. */
|
||||
%type <i_value> expression named_expression return_expression
|
||||
%type <a_value> opt_parameter_list parameter_list opt_auto_define_list
|
||||
%type <a_value> define_list opt_argument_list argument_list
|
||||
%type <i_value> program input_item semicolon_list statement_list
|
||||
%type <i_value> statement_or_error statement function relational_expression
|
||||
|
||||
/* precedence */
|
||||
%nonassoc REL_OP
|
||||
%right ASSIGN_OP
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%right '^'
|
||||
%nonassoc UNARY_MINUS
|
||||
%nonassoc INCR_DECR
|
||||
|
||||
%%
|
||||
program : /* empty */
|
||||
{
|
||||
$$ = 0;
|
||||
std_only = TRUE;
|
||||
if (interactive && !quiet)
|
||||
{
|
||||
show_bc_version ();
|
||||
welcome ();
|
||||
}
|
||||
}
|
||||
| program input_item
|
||||
;
|
||||
input_item : semicolon_list ENDOFLINE
|
||||
{ run_code (); }
|
||||
| function
|
||||
{ run_code (); }
|
||||
| error ENDOFLINE
|
||||
{
|
||||
yyerrok;
|
||||
init_gen () ;
|
||||
}
|
||||
;
|
||||
semicolon_list : /* empty */
|
||||
{ $$ = 0; }
|
||||
| statement_or_error
|
||||
| semicolon_list ';' statement_or_error
|
||||
| semicolon_list ';'
|
||||
;
|
||||
statement_list : /* empty */
|
||||
{ $$ = 0; }
|
||||
| statement
|
||||
| statement_list ENDOFLINE
|
||||
| statement_list ENDOFLINE statement
|
||||
| statement_list ';'
|
||||
| statement_list ';' statement
|
||||
;
|
||||
statement_or_error : statement
|
||||
| error statement
|
||||
{ $$ = $2; }
|
||||
;
|
||||
statement : Warranty
|
||||
{ warranty ("s"); }
|
||||
| expression
|
||||
{
|
||||
if ($1 & 1)
|
||||
generate ("W");
|
||||
else
|
||||
generate ("p");
|
||||
}
|
||||
| STRING
|
||||
{
|
||||
$$ = 0;
|
||||
generate ("w");
|
||||
generate ($1);
|
||||
free ($1);
|
||||
}
|
||||
| Break
|
||||
{
|
||||
if (break_label == 0)
|
||||
yyerror ("Break outside a for/while");
|
||||
else
|
||||
{
|
||||
sprintf (genstr, "J%1d:", break_label);
|
||||
generate (genstr);
|
||||
}
|
||||
}
|
||||
| Quit
|
||||
{ bc_exit (0); }
|
||||
| Return
|
||||
{ generate ("0R"); }
|
||||
| Return '(' return_expression ')'
|
||||
{ generate ("R"); }
|
||||
| For
|
||||
{
|
||||
$1 = break_label;
|
||||
break_label = next_label++;
|
||||
}
|
||||
'(' expression ';'
|
||||
{
|
||||
$4 = next_label++;
|
||||
sprintf (genstr, "pN%1d:", $4);
|
||||
generate (genstr);
|
||||
}
|
||||
relational_expression ';'
|
||||
{
|
||||
$7 = next_label++;
|
||||
sprintf (genstr, "B%1d:J%1d:", $7, break_label);
|
||||
generate (genstr);
|
||||
$<i_value>$ = next_label++;
|
||||
sprintf (genstr, "N%1d:", $<i_value>$);
|
||||
generate (genstr);
|
||||
}
|
||||
expression ')'
|
||||
{
|
||||
sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
|
||||
generate (genstr);
|
||||
}
|
||||
statement
|
||||
{
|
||||
sprintf (genstr, "J%1d:N%1d:", $<i_value>9,
|
||||
break_label);
|
||||
generate (genstr);
|
||||
break_label = $1;
|
||||
}
|
||||
| If '(' relational_expression ')'
|
||||
{
|
||||
$3 = next_label++;
|
||||
sprintf (genstr, "Z%1d:", $3);
|
||||
generate (genstr);
|
||||
}
|
||||
statement
|
||||
{
|
||||
sprintf (genstr, "N%1d:", $3);
|
||||
generate (genstr);
|
||||
}
|
||||
| While
|
||||
{
|
||||
$1 = next_label++;
|
||||
sprintf (genstr, "N%1d:", $1);
|
||||
generate (genstr);
|
||||
}
|
||||
'(' relational_expression
|
||||
{
|
||||
$4 = break_label;
|
||||
break_label = next_label++;
|
||||
sprintf (genstr, "Z%1d:", break_label);
|
||||
generate (genstr);
|
||||
}
|
||||
')' statement
|
||||
{
|
||||
sprintf (genstr, "J%1d:N%1d:", $1, break_label);
|
||||
generate (genstr);
|
||||
break_label = $4;
|
||||
}
|
||||
| '{' statement_list '}'
|
||||
{ $$ = 0; }
|
||||
;
|
||||
function : Define NAME '(' opt_parameter_list ')' '{'
|
||||
ENDOFLINE opt_auto_define_list
|
||||
{ char *params, *autos;
|
||||
check_params ($4,$8);
|
||||
params = arg_str ($4);
|
||||
autos = arg_str ($8);
|
||||
set_genstr_size (30 + strlen (params)
|
||||
+ strlen (autos));
|
||||
sprintf (genstr, "F%d,%s.%s[", lookup ($2,FUNCT),
|
||||
params, autos);
|
||||
generate (genstr);
|
||||
free_args ($4);
|
||||
free_args ($8);
|
||||
$1 = next_label;
|
||||
next_label = 0;
|
||||
}
|
||||
statement_list ENDOFLINE '}'
|
||||
{
|
||||
generate ("0R]");
|
||||
next_label = $1;
|
||||
}
|
||||
;
|
||||
opt_parameter_list : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| parameter_list
|
||||
;
|
||||
parameter_list : NAME
|
||||
{ $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE); }
|
||||
| define_list ',' NAME
|
||||
{ $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
|
||||
;
|
||||
opt_auto_define_list : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| Auto define_list ENDOFLINE
|
||||
{ $$ = $2; }
|
||||
| Auto define_list ';'
|
||||
{ $$ = $2; }
|
||||
;
|
||||
define_list : NAME
|
||||
{ $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE); }
|
||||
| NAME '[' ']'
|
||||
{ $$ = nextarg (NULL, lookup ($1,ARRAY), FALSE); }
|
||||
| define_list ',' NAME
|
||||
{ $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
|
||||
| define_list ',' NAME '[' ']'
|
||||
{ $$ = nextarg ($1, lookup ($3,ARRAY), FALSE); }
|
||||
;
|
||||
opt_argument_list : /* empty */
|
||||
{ $$ = NULL; }
|
||||
| argument_list
|
||||
;
|
||||
argument_list : expression
|
||||
{ $$ = nextarg (NULL,0, FALSE); }
|
||||
| argument_list ',' expression
|
||||
{ $$ = nextarg ($1,0, FALSE); }
|
||||
;
|
||||
relational_expression : expression
|
||||
{ $$ = 0; }
|
||||
| expression REL_OP expression
|
||||
{
|
||||
$$ = 0;
|
||||
switch (*($2))
|
||||
{
|
||||
case '=':
|
||||
generate ("=");
|
||||
break;
|
||||
case '!':
|
||||
generate ("#");
|
||||
break;
|
||||
case '<':
|
||||
if ($2[1] == '=')
|
||||
generate ("{");
|
||||
else
|
||||
generate ("<");
|
||||
break;
|
||||
case '>':
|
||||
if ($2[1] == '=')
|
||||
generate ("}");
|
||||
else
|
||||
generate (">");
|
||||
break;
|
||||
}
|
||||
}
|
||||
;
|
||||
return_expression : /* empty */
|
||||
{
|
||||
$$ = 0;
|
||||
generate ("0");
|
||||
}
|
||||
| expression
|
||||
;
|
||||
expression : named_expression ASSIGN_OP
|
||||
{
|
||||
if ($2 != '=')
|
||||
{
|
||||
if ($1 < 0)
|
||||
sprintf (genstr, "DL%d:", -$1);
|
||||
else
|
||||
sprintf (genstr, "l%d:", $1);
|
||||
generate (genstr);
|
||||
}
|
||||
}
|
||||
expression
|
||||
{
|
||||
$$ = 0;
|
||||
if ($2 != '=')
|
||||
{
|
||||
sprintf (genstr, "%c", $2);
|
||||
generate (genstr);
|
||||
}
|
||||
if ($1 < 0)
|
||||
sprintf (genstr, "S%d:", -$1);
|
||||
else
|
||||
sprintf (genstr, "s%d:", $1);
|
||||
generate (genstr);
|
||||
}
|
||||
| expression '+' expression
|
||||
{ generate ("+"); }
|
||||
| expression '-' expression
|
||||
{ generate ("-"); }
|
||||
| expression '*' expression
|
||||
{ generate ("*"); }
|
||||
| expression '/' expression
|
||||
{ generate ("/"); }
|
||||
| expression '%' expression
|
||||
{ generate ("%"); }
|
||||
| expression '^' expression
|
||||
{ generate ("^"); }
|
||||
| '-' expression %prec UNARY_MINUS
|
||||
{ generate ("n"); $$ = 1;}
|
||||
| named_expression
|
||||
{
|
||||
$$ = 1;
|
||||
if ($1 < 0)
|
||||
sprintf (genstr, "L%d:", -$1);
|
||||
else
|
||||
sprintf (genstr, "l%d:", $1);
|
||||
generate (genstr);
|
||||
}
|
||||
| NUMBER
|
||||
{
|
||||
int len = strlen ($1);
|
||||
$$ = 1;
|
||||
if (len == 1 && *$1 == '0')
|
||||
generate ("0");
|
||||
else
|
||||
{
|
||||
if (len == 1 && *$1 == '1')
|
||||
generate ("1");
|
||||
else
|
||||
{
|
||||
generate ("K");
|
||||
generate ($1);
|
||||
generate (":");
|
||||
}
|
||||
free ($1);
|
||||
}
|
||||
}
|
||||
| '(' expression ')'
|
||||
{ $$ = 1; }
|
||||
| NAME '(' opt_argument_list ')'
|
||||
{
|
||||
$$ = 1;
|
||||
if ($3 != NULL)
|
||||
{ char *params = call_str ($3);
|
||||
set_genstr_size (20 + strlen (params));
|
||||
sprintf (genstr, "C%d,%s:",
|
||||
lookup ($1,FUNCT), params);
|
||||
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; }
|
||||
;
|
||||
|
||||
%%
|
|
@ -0,0 +1,368 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* scan.l: the (f)lex description file for the scanner. */
|
||||
|
||||
%{
|
||||
|
||||
#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
|
||||
int yywrap (void);
|
||||
|
||||
#if defined(LIBEDIT)
|
||||
/* Support for the BSD libedit with history for
|
||||
nicer input on the interactive part of input. */
|
||||
|
||||
#include <histedit.h>
|
||||
|
||||
/* Have input call the following function. */
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
bcel_input((char *)buf, (yy_size_t *)&result, max_size)
|
||||
|
||||
/* Variables to help interface editline with bc. */
|
||||
static const char *bcel_line = (char *)NULL;
|
||||
static int bcel_len = 0;
|
||||
|
||||
/* bcel_input puts upto MAX characters into BUF with the number put in
|
||||
BUF placed in *RESULT. If the yy input file is the same as
|
||||
stdin, use editline. Otherwise, just read it.
|
||||
*/
|
||||
|
||||
static void
|
||||
bcel_input (char *buf, yy_size_t *result, int max)
|
||||
{
|
||||
ssize_t rdsize;
|
||||
if (!edit || yyin != stdin)
|
||||
{
|
||||
while ( (rdsize = read( fileno(yyin), buf, max )) < 0 )
|
||||
if (errno != EINTR)
|
||||
{
|
||||
yyerror( "read() in flex scanner failed" );
|
||||
bc_exit (1);
|
||||
}
|
||||
*result = (yy_size_t) rdsize;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do we need a new string? */
|
||||
if (bcel_len == 0)
|
||||
{
|
||||
bcel_line = el_gets(edit, &bcel_len);
|
||||
if (bcel_line == NULL) {
|
||||
/* end of file */
|
||||
*result = 0;
|
||||
bcel_len = 0;
|
||||
return;
|
||||
}
|
||||
if (bcel_len != 0)
|
||||
history (hist, &histev, H_ENTER, bcel_line);
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
if (bcel_len <= max)
|
||||
{
|
||||
strncpy (buf, bcel_line, bcel_len);
|
||||
*result = bcel_len;
|
||||
bcel_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy (buf, bcel_line, max);
|
||||
*result = max;
|
||||
bcel_line += max;
|
||||
bcel_len -= max;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef READLINE
|
||||
/* Support for the readline and history libraries. This allows
|
||||
nicer input on the interactive part of input. */
|
||||
|
||||
/* Have input call the following function. */
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
rl_input((char *)buf, &result, max_size)
|
||||
|
||||
/* Variables to help interface readline with bc. */
|
||||
static char *rl_line = (char *)NULL;
|
||||
static char *rl_start = (char *)NULL;
|
||||
static int rl_len = 0;
|
||||
|
||||
/* Definitions for readline access. */
|
||||
extern FILE *rl_instream;
|
||||
|
||||
/* rl_input puts upto MAX characters into BUF with the number put in
|
||||
BUF placed in *RESULT. If the yy input file is the same as
|
||||
rl_instream (stdin), use readline. Otherwise, just read it.
|
||||
*/
|
||||
|
||||
static void
|
||||
rl_input (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" );
|
||||
bc_exit (1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do we need a new string? */
|
||||
if (rl_len == 0)
|
||||
{
|
||||
if (rl_start)
|
||||
free(rl_start);
|
||||
rl_start = readline ("");
|
||||
if (rl_start == NULL) {
|
||||
/* end of file */
|
||||
*result = 0;
|
||||
rl_len = 0;
|
||||
return;
|
||||
}
|
||||
rl_line = rl_start;
|
||||
rl_len = strlen (rl_line)+1;
|
||||
if (rl_len != 1)
|
||||
add_history (rl_line);
|
||||
rl_line[rl_len-1] = '\n';
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
if (rl_len <= max)
|
||||
{
|
||||
strncpy (buf, rl_line, rl_len);
|
||||
*result = rl_len;
|
||||
rl_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy (buf, rl_line, max);
|
||||
*result = max;
|
||||
rl_line += max;
|
||||
rl_len -= max;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(READLINE) && !defined(LIBEDIT)
|
||||
|
||||
/* MINIX returns from read with < 0 if SIGINT is encountered.
|
||||
In flex, we can redefine YY_INPUT to the following. In lex, this
|
||||
does nothing! */
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
|
||||
if (errno != EINTR) \
|
||||
YY_FATAL_ERROR( "read() in flex scanner failed" );
|
||||
#endif
|
||||
|
||||
%}
|
||||
DIGIT [0-9A-Z]
|
||||
LETTER [a-z]
|
||||
%s slcomment
|
||||
%%
|
||||
"#" {
|
||||
if (!std_only)
|
||||
BEGIN(slcomment);
|
||||
else
|
||||
yyerror ("illegal character: #");
|
||||
}
|
||||
<slcomment>[^\n]* { BEGIN(INITIAL); }
|
||||
<slcomment>"\n" { line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
|
||||
define return(Define);
|
||||
break return(Break);
|
||||
quit return(Quit);
|
||||
length return(Length);
|
||||
return return(Return);
|
||||
for return(For);
|
||||
if return(If);
|
||||
while return(While);
|
||||
sqrt return(Sqrt);
|
||||
scale return(Scale);
|
||||
ibase return(Ibase);
|
||||
obase return(Obase);
|
||||
auto return(Auto);
|
||||
else return(Else);
|
||||
read return(Read);
|
||||
random return(Random);
|
||||
halt return(Halt);
|
||||
last return(Last);
|
||||
void return(Void);
|
||||
history {
|
||||
#if defined(READLINE) || defined(LIBEDIT)
|
||||
return(HistoryVar);
|
||||
#else
|
||||
yylval.s_value = strcopyof(yytext); return(NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
warranty return(Warranty);
|
||||
continue return(Continue);
|
||||
print return(Print);
|
||||
limits return(Limits);
|
||||
"." {
|
||||
#ifdef DOT_IS_LAST
|
||||
return(Last);
|
||||
#else
|
||||
yyerror ("illegal character: %s",yytext);
|
||||
#endif
|
||||
}
|
||||
"+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0];
|
||||
return((int)yytext[0]); }
|
||||
&& { return(AND); }
|
||||
\|\| { return(OR); }
|
||||
"!" { return(NOT); }
|
||||
"*"|"/"|"%"|"&" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
|
||||
"="|\+=|-=|\*=|\/=|%=|\^= { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
|
||||
=\+|=-|=\*|=\/|=%|=\^ {
|
||||
#ifdef OLD_EQ_OP
|
||||
char warn_save;
|
||||
warn_save = warn_not_std;
|
||||
warn_not_std = TRUE;
|
||||
ct_warn ("Old fashioned =<op>");
|
||||
warn_not_std = warn_save;
|
||||
yylval.c_value = yytext[1];
|
||||
#else
|
||||
yylval.c_value = '=';
|
||||
yyless (1);
|
||||
#endif
|
||||
return(ASSIGN_OP);
|
||||
}
|
||||
==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof(yytext); return(REL_OP); }
|
||||
\+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
|
||||
"\n" { line_no++; return(ENDOFLINE); }
|
||||
\\\n { line_no++; /* ignore a "quoted" newline */ }
|
||||
[ \t]+ { /* ignore spaces and tabs */ }
|
||||
"/*" {
|
||||
int c;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
while ( ((c=input()) != '*') && (c != EOF))
|
||||
/* eat it */
|
||||
if (c == '\n') line_no++;
|
||||
if (c == '*')
|
||||
{
|
||||
while ( (c=input()) == '*') /* eat it*/;
|
||||
if (c == '/') break; /* at end of comment */
|
||||
if (c == '\n') line_no++;
|
||||
}
|
||||
if (c == EOF)
|
||||
{
|
||||
fprintf (stderr,"EOF encountered in a comment.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
|
||||
\"[^\"]*\" {
|
||||
const 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)* {
|
||||
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++;
|
||||
}
|
||||
if (*src == ',')
|
||||
{
|
||||
src++;
|
||||
ct_warn("Commas in numbers");
|
||||
}
|
||||
else
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = 0;
|
||||
yylval.s_value = strcopyof(yytext);
|
||||
return(NUMBER);
|
||||
}
|
||||
. {
|
||||
if (yytext[0] < ' ')
|
||||
yyerror ("illegal character: ^%c",yytext[0] + '@');
|
||||
else
|
||||
if (yytext[0] > '~')
|
||||
yyerror ("illegal character: \\%03o", (int) yytext[0]);
|
||||
else
|
||||
yyerror ("illegal character: %s",yytext);
|
||||
}
|
||||
%%
|
||||
|
||||
|
||||
|
||||
/* This is the way to get multiple files input into lex. */
|
||||
|
||||
int
|
||||
yywrap(void)
|
||||
{
|
||||
if (!open_new_file ()) return (1); /* EOF on standard in. */
|
||||
return (0); /* We have more input. */
|
||||
yyunput(0,NULL); /* Make sure the compiler think yyunput is used. */
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,838 @@
|
|||
/* This file is part of GNU bc.
|
||||
|
||||
Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 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 3 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, see
|
||||
<http://www.gnu.org/licenses>.
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
/* util.c: Utility routines for bc. */
|
||||
|
||||
#include "bcdefs.h"
|
||||
#ifndef VARARGS
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include "proto.h"
|
||||
|
||||
|
||||
/* strcopyof mallocs new memory and copies a string to to the new
|
||||
memory. */
|
||||
|
||||
char *
|
||||
strcopyof (const char *str)
|
||||
{
|
||||
char *temp;
|
||||
|
||||
temp = bc_malloc (strlen (str)+1);
|
||||
return (strcpy (temp,str));
|
||||
}
|
||||
|
||||
|
||||
/* nextarg adds another value to the list of arguments. */
|
||||
|
||||
arg_list *
|
||||
nextarg (arg_list *args, int val, int is_var)
|
||||
{ arg_list *temp;
|
||||
|
||||
temp = 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.
|
||||
*/
|
||||
|
||||
static char *make_arg_str (arg_list *args, int len);
|
||||
|
||||
static char *
|
||||
make_arg_str (arg_list *args, int len)
|
||||
{
|
||||
char *temp;
|
||||
char sval[30];
|
||||
|
||||
/* Recursive call. */
|
||||
if (args != NULL)
|
||||
temp = make_arg_str (args->next, len+12);
|
||||
else
|
||||
{
|
||||
temp = 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)
|
||||
snprintf (sval, sizeof(sval), "*%d,", args->av_name);
|
||||
else
|
||||
snprintf (sval, sizeof(sval), "*%d", args->av_name);
|
||||
else
|
||||
if (len != 1)
|
||||
snprintf (sval, sizeof(sval), "%d,", args->av_name);
|
||||
else
|
||||
snprintf (sval, sizeof(sval), "%d", args->av_name);
|
||||
temp = strcat (temp, sval);
|
||||
return (temp);
|
||||
}
|
||||
|
||||
char *
|
||||
arg_str (arg_list *args)
|
||||
{
|
||||
if (arglist2 != NULL)
|
||||
free (arglist2);
|
||||
arglist2 = arglist1;
|
||||
arglist1 = make_arg_str (args, 1);
|
||||
return (arglist1);
|
||||
}
|
||||
|
||||
char *
|
||||
call_str (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 = 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 (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 (arg_list *params, arg_list *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)
|
||||
ct_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* genstr management to avoid buffer overflow. */
|
||||
void
|
||||
set_genstr_size (int size)
|
||||
{
|
||||
if (size > genlen) {
|
||||
if (genstr != NULL)
|
||||
free(genstr);
|
||||
genstr = bc_malloc (size);
|
||||
genlen = size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the code generator the parser. */
|
||||
|
||||
void
|
||||
init_gen (void)
|
||||
{
|
||||
/* 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;
|
||||
set_genstr_size (64);
|
||||
}
|
||||
|
||||
|
||||
/* generate code STR for the machine. */
|
||||
|
||||
void
|
||||
generate (const 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(void)
|
||||
{
|
||||
/* 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 (int ch)
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
out_col = 0;
|
||||
putchar ('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
out_col++;
|
||||
if (out_col == line_size-1 && line_size != 0)
|
||||
{
|
||||
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 (int ch)
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
out_col = 0;
|
||||
putchar ('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!std_only)
|
||||
{
|
||||
out_col++;
|
||||
if (out_col == line_size-1 && line_size != 0)
|
||||
{
|
||||
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 (id_rec *tree, const 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 (id_rec **root, id_rec *new_id)
|
||||
{
|
||||
id_rec *A, *B;
|
||||
|
||||
/* If root is NULL, this where it is to be inserted. */
|
||||
if (*root == NULL)
|
||||
{
|
||||
*root = new_id;
|
||||
new_id->left = NULL;
|
||||
new_id->right = NULL;
|
||||
new_id->balance = 0;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* We need to search for a leaf. */
|
||||
if (strcmp (new_id->id, (*root)->id) < 0)
|
||||
{
|
||||
/* Insert it on the left. */
|
||||
if (insert_id_rec (&((*root)->left), new_id))
|
||||
{
|
||||
/* The height increased. */
|
||||
(*root)->balance --;
|
||||
|
||||
switch ((*root)->balance)
|
||||
{
|
||||
case 0: /* no height increase. */
|
||||
return (FALSE);
|
||||
case -1: /* height increase. */
|
||||
return (TRUE);
|
||||
case -2: /* we need to do a rebalancing act. */
|
||||
A = *root;
|
||||
B = (*root)->left;
|
||||
if (B->balance <= 0)
|
||||
{
|
||||
/* Single Rotate. */
|
||||
A->left = B->right;
|
||||
B->right = A;
|
||||
*root = B;
|
||||
A->balance = 0;
|
||||
B->balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Double Rotate. */
|
||||
*root = B->right;
|
||||
B->right = (*root)->left;
|
||||
A->left = (*root)->right;
|
||||
(*root)->left = B;
|
||||
(*root)->right = A;
|
||||
switch ((*root)->balance)
|
||||
{
|
||||
case -1:
|
||||
A->balance = 1;
|
||||
B->balance = 0;
|
||||
break;
|
||||
case 0:
|
||||
A->balance = 0;
|
||||
B->balance = 0;
|
||||
break;
|
||||
case 1:
|
||||
A->balance = 0;
|
||||
B->balance = -1;
|
||||
break;
|
||||
}
|
||||
(*root)->balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Insert it on the right. */
|
||||
if (insert_id_rec (&((*root)->right), new_id))
|
||||
{
|
||||
/* The height increased. */
|
||||
(*root)->balance ++;
|
||||
|
||||
switch ((*root)->balance)
|
||||
{
|
||||
case 0: /* no height increase. */
|
||||
return (FALSE);
|
||||
case 1: /* height increase. */
|
||||
return (TRUE);
|
||||
case 2: /* we need to do a rebalancing act. */
|
||||
A = *root;
|
||||
B = (*root)->right;
|
||||
if (B->balance >= 0)
|
||||
{
|
||||
/* Single Rotate. */
|
||||
A->right = B->left;
|
||||
B->left = A;
|
||||
*root = B;
|
||||
A->balance = 0;
|
||||
B->balance = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Double Rotate. */
|
||||
*root = B->left;
|
||||
B->left = (*root)->right;
|
||||
A->right = (*root)->left;
|
||||
(*root)->left = A;
|
||||
(*root)->right = B;
|
||||
switch ((*root)->balance)
|
||||
{
|
||||
case -1:
|
||||
A->balance = 0;
|
||||
B->balance = 1;
|
||||
break;
|
||||
case 0:
|
||||
A->balance = 0;
|
||||
B->balance = 0;
|
||||
break;
|
||||
case 1:
|
||||
A->balance = -1;
|
||||
B->balance = 0;
|
||||
break;
|
||||
}
|
||||
(*root)->balance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we fall through to here, the tree did not grow in height. */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize variables for the symbol table tree. */
|
||||
|
||||
void
|
||||
init_tree(void)
|
||||
{
|
||||
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 (char *name, int namekind)
|
||||
{
|
||||
id_rec *id;
|
||||
|
||||
/* Warn about non-standard name. */
|
||||
if (strlen(name) != 1)
|
||||
ct_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 = 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++;
|
||||
if (id->a_name < MAX_STORE)
|
||||
{
|
||||
if (id->a_name >= a_count)
|
||||
more_arrays ();
|
||||
a_names[id->a_name] = name;
|
||||
return (-id->a_name);
|
||||
}
|
||||
yyerror ("Too many array variables");
|
||||
bc_exit (1);
|
||||
/*NOTREACHED*/
|
||||
|
||||
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++;
|
||||
if (id->f_name < MAX_STORE)
|
||||
{
|
||||
if (id->f_name >= f_count)
|
||||
more_functions ();
|
||||
f_names[id->f_name] = name;
|
||||
return (id->f_name);
|
||||
}
|
||||
yyerror ("Too many functions");
|
||||
bc_exit (1);
|
||||
/*NOTREACHED*/
|
||||
|
||||
case SIMPLE:
|
||||
if (id->v_name != 0)
|
||||
{
|
||||
free(name);
|
||||
return (id->v_name);
|
||||
}
|
||||
id->v_name = next_var++;
|
||||
if (id->v_name <= MAX_STORE)
|
||||
{
|
||||
if (id->v_name >= v_count)
|
||||
more_variables ();
|
||||
v_names[id->v_name - 1] = name;
|
||||
return (id->v_name);
|
||||
}
|
||||
yyerror ("Too many variables");
|
||||
bc_exit (1);
|
||||
/*NOTREACHED*/
|
||||
|
||||
}
|
||||
|
||||
yyerror ("End of util.c/lookup() reached. Please report this bug.");
|
||||
bc_exit (1);
|
||||
/*NOTREACHED*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Print out the limits of this program. */
|
||||
|
||||
void
|
||||
limits(void)
|
||||
{
|
||||
printf ("BC_BASE_MAX = %d\n", BC_BASE_MAX);
|
||||
printf ("BC_DIM_MAX = %ld\n", (long) BC_DIM_MAX);
|
||||
printf ("BC_SCALE_MAX = %d\n", BC_SCALE_MAX);
|
||||
printf ("BC_STRING_MAX = %d\n", BC_STRING_MAX);
|
||||
printf ("MAX Exponent = %ld\n", (long) LONG_MAX);
|
||||
printf ("Number of vars = %ld\n", (long) MAX_STORE);
|
||||
#ifdef OLD_EQ_OP
|
||||
printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* bc_malloc will check the return value so all other places do not
|
||||
have to do it! SIZE is the number of bytes to allocate. */
|
||||
|
||||
void *
|
||||
bc_malloc (size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = (void *) 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(void)
|
||||
{
|
||||
fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
|
||||
bc_exit (1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The standard yyerror routine. Built with variable number of argumnets. */
|
||||
|
||||
#ifndef VARARGS
|
||||
#ifdef __STDC__
|
||||
void
|
||||
yyerror (const char *str, ...)
|
||||
#else
|
||||
void
|
||||
yyerror (str)
|
||||
const char *str;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
yyerror (str, va_alist)
|
||||
const char *str;
|
||||
#endif
|
||||
{
|
||||
const 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
|
||||
ct_warn (const char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
ct_warn (mesg)
|
||||
const char *mesg;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
ct_warn (mesg, va_alist)
|
||||
const char *mesg;
|
||||
#endif
|
||||
{
|
||||
const 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: Error: ",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 (const char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
rt_error (mesg)
|
||||
const char *mesg;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
rt_error (mesg, va_alist)
|
||||
const char *mesg;
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fprintf (stderr, "Runtime error (func=%s, adr=%d): ",
|
||||
f_names[pc.pc_func], pc.pc_addr);
|
||||
#ifndef VARARGS
|
||||
va_start (args, mesg);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
vfprintf (stderr, mesg, args);
|
||||
va_end (args);
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
runtime_error = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* A runtime warning tells of some action taken by the processor that
|
||||
may change the program execution but was not enough of a problem
|
||||
to stop the execution. */
|
||||
|
||||
#ifndef VARARGS
|
||||
#ifdef __STDC__
|
||||
void
|
||||
rt_warn (const char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
rt_warn (const char *mesg)
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
rt_warn (const char *mesg)
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fprintf (stderr, "Runtime warning (func=%s, adr=%d): ",
|
||||
f_names[pc.pc_func], pc.pc_addr);
|
||||
#ifndef VARARGS
|
||||
va_start (args, mesg);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
vfprintf (stderr, mesg, args);
|
||||
va_end (args);
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
/* bc_exit: Make sure to reset the edit state. */
|
||||
|
||||
void bc_exit(int val)
|
||||
{
|
||||
#if defined(LIBEDIT)
|
||||
if (edit != NULL)
|
||||
el_end(edit);
|
||||
#endif
|
||||
exit(val);
|
||||
/*NOTREACHED*/
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* warranty.c: warranty routines for bc. */
|
||||
|
||||
/* This file is part of GNU bc.
|
||||
Copyright (C) 1991-1994, 1997, 2000, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License , or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
The Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor
|
||||
Boston, MA 02110-1335 USA
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#include "bcdefs.h"
|
||||
#include "proto.h"
|
||||
|
||||
|
||||
/* Print the welcome banner. */
|
||||
|
||||
void
|
||||
welcome()
|
||||
{
|
||||
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n");
|
||||
printf ("For details type `warranty'. \n");
|
||||
}
|
||||
|
||||
/* Print out the version information. */
|
||||
void
|
||||
show_bc_version()
|
||||
{
|
||||
printf("%s %s\n%s\n", PACKAGE, VERSION, BC_COPYRIGHT);
|
||||
}
|
||||
|
||||
|
||||
/* Print out the warranty information. */
|
||||
|
||||
void
|
||||
warranty(prefix)
|
||||
const char *prefix;
|
||||
{
|
||||
printf ("\n%s", prefix);
|
||||
show_bc_version ();
|
||||
printf ("\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 3 of the License , or\n"
|
||||
" (at your option) any later version.\n\n"
|
||||
" This program is distributed in the hope that it will be useful,\n"
|
||||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n\n"
|
||||
" You should have received a copy of the GNU General Public License\n"
|
||||
" along with this program. If not, write to\n\n"
|
||||
" The Free Software Foundation, Inc.\n"
|
||||
" 51 Franklin Street, Fifth Floor\n"
|
||||
" Boston, MA 02110-1335 USA\n\n");
|
||||
}
|
|
@ -0,0 +1,347 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,148 @@
|
|||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define the bc copyright line. */
|
||||
#undef BC_COPYRIGHT
|
||||
|
||||
/* Define the dc copyright line. */
|
||||
#undef DC_COPYRIGHT
|
||||
|
||||
/* Define the dc version number. */
|
||||
#undef DC_VERSION
|
||||
|
||||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||
#undef HAVE_DOPRNT
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#undef HAVE_ERRNO_H
|
||||
|
||||
/* Define to 1 if you have the `fstat' function. */
|
||||
#undef HAVE_FSTAT
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `isgraph' function. */
|
||||
#undef HAVE_ISGRAPH
|
||||
|
||||
/* Define to 1 if you have the <lib.h> header file. */
|
||||
#undef HAVE_LIB_H
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `setvbuf' function. */
|
||||
#undef HAVE_SETVBUF
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strtol' function. */
|
||||
#undef HAVE_STRTOL
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `vprintf' function. */
|
||||
#undef HAVE_VPRINTF
|
||||
|
||||
/* Define if libedit is used */
|
||||
#undef LIBEDIT
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define if readline is used */
|
||||
#undef READLINE
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
||||
`char[]'. */
|
||||
#undef YYTEXT_POINTER
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `size_t' if <sys/types.h> does not define. */
|
||||
#undef ptrdiff_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,128 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
dnl Copyright (C) 2006, 2016 Free Software Foundation, Inc.
|
||||
dnl
|
||||
dnl This program is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 3, or (at your option)
|
||||
dnl any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
dnl GNU General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
> dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
m4_define([bc_version], 1.07.1)
|
||||
m4_define([dc_version], 1.4.1)
|
||||
|
||||
AC_INIT([bc],[bc_version])
|
||||
AC_CONFIG_SRCDIR(doc/bc.1)
|
||||
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
AC_DEFINE([DC_VERSION], "dc_version",
|
||||
[Define the dc version number.])
|
||||
|
||||
AC_DEFINE([BC_COPYRIGHT],
|
||||
["Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc."],
|
||||
[Define the bc copyright line.])
|
||||
|
||||
AC_DEFINE([DC_COPYRIGHT],
|
||||
["Copyright 1994, 1997, 1998, 2000, 2001, 2003-2006, 2008, 2010, 2012-2017 Free Software Foundation, Inc."],
|
||||
[Define the dc copyright line.])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
AM_PROG_LEX
|
||||
AM_PROG_AR
|
||||
AC_PROG_YACC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
AC_CHECK_HEADERS_ONCE(stdarg.h stddef.h stdlib.h string.h errno.h limits.h unistd.h lib.h)
|
||||
AC_C_CONST
|
||||
AC_TYPE_SIZE_T
|
||||
AC_CHECK_TYPE(ptrdiff_t, size_t)
|
||||
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS(isgraph setvbuf fstat strtol)
|
||||
|
||||
AC_ARG_WITH(pkg,
|
||||
AS_HELP_STRING([--with-pkg],[use software installed in /usr/pkg tree]),
|
||||
[case $withval in no) ;;
|
||||
*) CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
|
||||
LDFLAGS="$LDFLAGS -L/usr/pkg/lib"
|
||||
echo Using /usr/pkg/include and /usr/pkg/lib ;;
|
||||
esac])
|
||||
|
||||
bcle=n
|
||||
AC_ARG_WITH(libedit,
|
||||
AS_HELP_STRING([--with-libedit],[support fancy BSD command input editing]),
|
||||
[case $withval in no) ;;
|
||||
*) LDSAVE=$LDFLAGS
|
||||
AC_CHECK_LIB(termcap,tgetent,TERMLIB=-ltermcap)
|
||||
LDFLAGS="$LDFLAGS $TERMLIB"
|
||||
AC_CHECK_LIB(edit,el_gets,
|
||||
[AC_CHECK_HEADER(histedit.h,
|
||||
READLINELIB="-ledit $TERMLIB";bcle=y)],
|
||||
READLINELIB="")
|
||||
case $bcle in
|
||||
y) AC_DEFINE(LIBEDIT,1, [Define if libedit is used])
|
||||
echo Using the libedit library. ;;
|
||||
esac
|
||||
LDFLAGS=$LDSAVE
|
||||
;;
|
||||
esac])
|
||||
|
||||
bcrl=n
|
||||
AC_ARG_WITH(readline,
|
||||
AS_HELP_STRING([--with-readline],[support fancy command input editing]),
|
||||
[case $withval in no) ;;
|
||||
*) LDSAVE=$LDFLAGS
|
||||
AC_CHECK_LIB(ncurses,tparm,TERMLIB=-lncurses,
|
||||
AC_CHECK_LIB(termcap,tgetent,TERMLIB=-ltermcap))
|
||||
LDFLAGS="$LDFLAGS $TERMLIB"
|
||||
AC_CHECK_LIB(readline,readline,
|
||||
[AC_CHECK_HEADER(readline/readline.h,
|
||||
READLINELIB="-lreadline $TERMLIB";bcrl=y)],
|
||||
READLINELIB="")
|
||||
case $bcrl in
|
||||
y) AC_DEFINE(READLINE,1, [Define if readline is used])
|
||||
echo Using the readline library. ;;
|
||||
esac
|
||||
LDFLAGS=$LDSAVE
|
||||
;;
|
||||
esac])
|
||||
|
||||
case $bcle-$bcrl-$LEX in
|
||||
y-y-*)
|
||||
AC_MSG_ERROR(Can not use both readline and libedit. Aborting.) ;;
|
||||
?-?-flex)
|
||||
LEX="flex -I -8" ;;
|
||||
?-y-*)
|
||||
AC_MSG_ERROR(readline works only with flex.) ;;
|
||||
esac
|
||||
|
||||
case $LEX-`uname -s` in
|
||||
lex-SunOS) LEXLIB=""; echo "SunOS using lex does not have a -ll." ;;
|
||||
esac
|
||||
|
||||
case $GCC in
|
||||
yes) CFLAGS="$CFLAGS -Wall -funsigned-char"
|
||||
echo "Adding GCC specific compile flags." ;;
|
||||
esac
|
||||
|
||||
AC_SUBST(READLINELIB)
|
||||
AC_SUBST(BC_VERSION, bc_version)
|
||||
AC_SUBST(DC_VERSION, dc_version)
|
||||
AC_CONFIG_FILES(
|
||||
Makefile bc/Makefile dc/Makefile
|
||||
lib/Makefile
|
||||
doc/Makefile doc/texi-ver.incl
|
||||
)
|
||||
AC_OUTPUT
|
|
@ -0,0 +1,14 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
bin_PROGRAMS = dc
|
||||
|
||||
dc_SOURCES = dc.c misc.c eval.c stack.c array.c numeric.c string.c
|
||||
noinst_HEADERS = dc.h dc-proto.h dc-regdef.h
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir)/.. -I$(srcdir)/../h
|
||||
LDADD = ../lib/libbc.a
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
AM_CFLAGS = @CFLAGS@
|
||||
|
||||
$(PROGRAMS): $(LDADD)
|
|
@ -0,0 +1,579 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
bin_PROGRAMS = dc$(EXEEXT)
|
||||
subdir = dc
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/depcomp $(noinst_HEADERS)
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_dc_OBJECTS = dc.$(OBJEXT) misc.$(OBJEXT) eval.$(OBJEXT) \
|
||||
stack.$(OBJEXT) array.$(OBJEXT) numeric.$(OBJEXT) \
|
||||
string.$(OBJEXT)
|
||||
dc_OBJECTS = $(am_dc_OBJECTS)
|
||||
dc_LDADD = $(LDADD)
|
||||
dc_DEPENDENCIES = ../lib/libbc.a
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(dc_SOURCES)
|
||||
DIST_SOURCES = $(dc_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
HEADERS = $(noinst_HEADERS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BC_VERSION = @BC_VERSION@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DC_VERSION = @DC_VERSION@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
READLINELIB = @READLINELIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
YACC = @YACC@
|
||||
YFLAGS = @YFLAGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
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
|
||||
AM_CPPFLAGS = -I$(srcdir)/.. -I$(srcdir)/../h
|
||||
LDADD = ../lib/libbc.a
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
AM_CFLAGS = @CFLAGS@
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu dc/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu dc/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
|
||||
dc$(EXEEXT): $(dc_OBJECTS) $(dc_DEPENDENCIES) $(EXTRA_dc_DEPENDENCIES)
|
||||
@rm -f dc$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(dc_OBJECTS) $(dc_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numeric.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS) $(HEADERS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
|
||||
clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \
|
||||
distclean distclean-compile distclean-generic distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-binPROGRAMS install-data install-data-am \
|
||||
install-dvi install-dvi-am install-exec install-exec-am \
|
||||
install-html install-html-am install-info install-info-am \
|
||||
install-man install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
|
||||
ps ps-am tags tags-am uninstall uninstall-am \
|
||||
uninstall-binPROGRAMS
|
||||
|
||||
|
||||
$(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:
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* implement arrays for dc
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2000, 2006, 2008
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This module is the only one that knows what arrays look like. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h> /* "dc-proto.h" wants this */
|
||||
#ifdef HAVE_STDLIB_H
|
||||
/* get size_t definition from "almost ANSI" compiling environments. */
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "dc.h"
|
||||
#include "dc-proto.h"
|
||||
#include "dc-regdef.h"
|
||||
|
||||
/* what's most useful: quick access or sparse arrays? */
|
||||
/* I'll go with sparse arrays for now */
|
||||
struct dc_array {
|
||||
int Index;
|
||||
dc_data value;
|
||||
struct dc_array *next;
|
||||
};
|
||||
|
||||
|
||||
/* initialize the arrays */
|
||||
void
|
||||
dc_array_init DC_DECLVOID()
|
||||
{
|
||||
}
|
||||
|
||||
/* store value into array_id[Index] */
|
||||
void
|
||||
dc_array_set DC_DECLARG((array_id, Index, value))
|
||||
int array_id DC_DECLSEP
|
||||
int Index DC_DECLSEP
|
||||
dc_data value DC_DECLEND
|
||||
{
|
||||
struct dc_array *cur;
|
||||
struct dc_array *prev = NULL;
|
||||
|
||||
cur = dc_get_stacked_array(array_id);
|
||||
while (cur != NULL && cur->Index < Index){
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur != NULL && 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{
|
||||
struct dc_array *newentry = dc_malloc(sizeof *newentry);
|
||||
newentry->Index = Index;
|
||||
newentry->value = value;
|
||||
newentry->next = cur;
|
||||
if (prev != NULL)
|
||||
prev->next = newentry;
|
||||
else
|
||||
dc_set_stacked_array(array_id, newentry);
|
||||
}
|
||||
}
|
||||
|
||||
/* retrieve a dup of a value from array_id[Index] */
|
||||
/* A zero value is returned if the specified value is unintialized. */
|
||||
dc_data
|
||||
dc_array_get DC_DECLARG((array_id, Index))
|
||||
int array_id DC_DECLSEP
|
||||
int Index DC_DECLEND
|
||||
{
|
||||
struct dc_array *cur = dc_get_stacked_array(array_id);
|
||||
|
||||
while (cur != NULL && cur->Index < Index)
|
||||
cur = cur->next;
|
||||
if (cur !=NULL && cur->Index == Index)
|
||||
return dc_dup(cur->value);
|
||||
return dc_int2data(0);
|
||||
}
|
||||
|
||||
/* free an array chain */
|
||||
void
|
||||
dc_array_free DC_DECLARG((a_head))
|
||||
struct dc_array *a_head DC_DECLEND
|
||||
{
|
||||
struct dc_array *cur;
|
||||
struct dc_array *next;
|
||||
|
||||
for (cur=a_head; cur!=NULL; cur=next) {
|
||||
next = cur->next;
|
||||
if (cur->value.dc_type == DC_NUMBER)
|
||||
dc_free_num(&cur->value.v.number);
|
||||
else if (cur->value.dc_type == DC_STRING)
|
||||
dc_free_str(&cur->value.v.string);
|
||||
else
|
||||
dc_garbage("in stack", -1);
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* prototypes of all externally visible dc functions
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2003, 2008, 2012, 2013
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
extern const char *dc_str2charp DC_PROTO((dc_str));
|
||||
extern const char *dc_system DC_PROTO((const char *));
|
||||
extern void *dc_malloc DC_PROTO((size_t));
|
||||
extern struct dc_array *dc_get_stacked_array DC_PROTO((int));
|
||||
|
||||
extern void dc_array_set DC_PROTO((int, int, dc_data));
|
||||
extern void dc_array_free DC_PROTO((struct dc_array *));
|
||||
extern void dc_array_init DC_PROTO((void));
|
||||
extern void dc_binop DC_PROTO((int (*)(dc_num, dc_num, int, dc_num *), int));
|
||||
extern void dc_binop2 DC_PROTO((int (*)(dc_num, dc_num, int,
|
||||
dc_num *, dc_num *), int));
|
||||
extern void dc_triop DC_PROTO((int (*)(dc_num, dc_num, dc_num, int,
|
||||
dc_num *), int));
|
||||
extern void dc_clear_stack DC_PROTO((void));
|
||||
extern void dc_dump_num(dc_num, dc_discard);
|
||||
extern void dc_free_num DC_PROTO((dc_num *));
|
||||
extern void dc_free_str DC_PROTO((dc_str *));
|
||||
extern void dc_garbage DC_PROTO((const char *, int));
|
||||
extern void dc_math_init DC_PROTO((void));
|
||||
extern void dc_memfail DC_PROTO((void));
|
||||
extern void dc_out_num DC_PROTO((dc_num, int, dc_discard));
|
||||
extern void dc_out_str DC_PROTO((dc_str, dc_discard));
|
||||
extern void dc_print DC_PROTO((dc_data, int, dc_newline, dc_discard));
|
||||
extern void dc_printall DC_PROTO((int));
|
||||
extern void dc_push DC_PROTO((dc_data));
|
||||
extern void dc_register_init DC_PROTO((void));
|
||||
extern void dc_register_push DC_PROTO((int, dc_data));
|
||||
extern void dc_register_set DC_PROTO((int, dc_data));
|
||||
extern void dc_set_stacked_array DC_PROTO((int, struct dc_array *));
|
||||
extern void dc_show_id DC_PROTO((FILE *, int, const char *));
|
||||
extern void dc_string_init DC_PROTO((void));
|
||||
|
||||
extern int dc_cmpop DC_PROTO((void));
|
||||
extern int dc_compare DC_PROTO((dc_num, dc_num));
|
||||
extern int dc_evalfile DC_PROTO((FILE *));
|
||||
extern int dc_evalstr DC_PROTO((dc_data *));
|
||||
extern int dc_num2int DC_PROTO((dc_num, dc_discard));
|
||||
extern int dc_numlen DC_PROTO((dc_num));
|
||||
extern int dc_pop DC_PROTO((dc_data *));
|
||||
extern int dc_register_get DC_PROTO((int, dc_data *));
|
||||
extern int dc_register_pop DC_PROTO((int, dc_data *));
|
||||
extern void dc_stack_rotate DC_PROTO((int));
|
||||
extern int dc_tell_length DC_PROTO((dc_data, dc_discard));
|
||||
extern int dc_tell_scale DC_PROTO((dc_num, dc_discard));
|
||||
extern int dc_tell_stackdepth DC_PROTO((void));
|
||||
extern int dc_top_of_stack DC_PROTO((dc_data *));
|
||||
|
||||
extern size_t dc_strlen DC_PROTO((dc_str));
|
||||
|
||||
extern dc_data dc_array_get DC_PROTO((int, int));
|
||||
extern dc_data dc_dup DC_PROTO((dc_data));
|
||||
extern dc_data dc_dup_num DC_PROTO((dc_num));
|
||||
extern dc_data dc_dup_str DC_PROTO((dc_str));
|
||||
extern dc_data dc_getnum DC_PROTO((int (*)(void), int, int *));
|
||||
extern dc_data dc_int2data DC_PROTO((int));
|
||||
extern dc_data dc_makestring DC_PROTO((const char *, size_t));
|
||||
extern dc_data dc_readstring DC_PROTO((FILE *, int , int));
|
||||
|
||||
extern int dc_add DC_PROTO((dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_div DC_PROTO((dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_divrem DC_PROTO((dc_num, dc_num, int, dc_num *, dc_num *));
|
||||
extern int dc_exp DC_PROTO((dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_modexp DC_PROTO((dc_num, dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_mul DC_PROTO((dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_rem DC_PROTO((dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_sub DC_PROTO((dc_num, dc_num, int, dc_num *));
|
||||
extern int dc_sqrt DC_PROTO((dc_num, int, dc_num *));
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* definitions for dc's "register" declarations
|
||||
*
|
||||
* Copyright (C) 1994, 2000, 2008
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h> /* UCHAR_MAX */
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX ((unsigned char)~0)
|
||||
#endif
|
||||
|
||||
/* determine how many register stacks there are */
|
||||
#ifndef DC_REGCOUNT
|
||||
# define DC_REGCOUNT (UCHAR_MAX+1)
|
||||
#endif
|
||||
|
||||
/* 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
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* implement the "dc" Desk Calculator language.
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2000, 2003, 2006, 2008, 2013
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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
|
||||
#ifdef HAVE_FSTAT
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#include <getopt.h>
|
||||
#include "dc.h"
|
||||
#include "dc-proto.h"
|
||||
|
||||
#ifndef EXIT_SUCCESS /* C89 <stdlib.h> */
|
||||
# define EXIT_SUCCESS 0
|
||||
#endif
|
||||
#ifndef EXIT_FAILURE /* C89 <stdlib.h> */
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
const char *progname; /* basename of program invocation */
|
||||
|
||||
static void
|
||||
bug_report_info DC_DECLVOID()
|
||||
{
|
||||
printf("Email bug reports to: bug-dc@gnu.org .\n");
|
||||
}
|
||||
|
||||
static void
|
||||
show_version DC_DECLVOID()
|
||||
{
|
||||
printf("dc (GNU %s %s) %s\n", PACKAGE, VERSION, DC_VERSION);
|
||||
printf("\n%s\n\
|
||||
This is free software; see the source for copying conditions. There is NO\n\
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
|
||||
to the extent permitted by law.\n", DC_COPYRIGHT);
|
||||
}
|
||||
|
||||
/* your generic usage function */
|
||||
static void
|
||||
usage DC_DECLARG((f))
|
||||
FILE *f DC_DECLEND
|
||||
{
|
||||
fprintf(f, "\
|
||||
Usage: %s [OPTION] [file ...]\n\
|
||||
-e, --expression=EXPR evaluate expression\n\
|
||||
-f, --file=FILE evaluate contents of file\n\
|
||||
-h, --help display this help and exit\n\
|
||||
-V, --version output version information and exit\n\
|
||||
\n\
|
||||
", progname);
|
||||
bug_report_info();
|
||||
}
|
||||
|
||||
/* returns a pointer to one past the last occurance of c in s,
|
||||
* or s if c does not occur in s.
|
||||
*/
|
||||
static char *
|
||||
r1bindex DC_DECLARG((s, c))
|
||||
char *s DC_DECLSEP
|
||||
int c DC_DECLEND
|
||||
{
|
||||
char *p = strrchr(s, c);
|
||||
|
||||
if (p == NULL)
|
||||
return s;
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
try_file(const char *filename)
|
||||
{
|
||||
FILE *input;
|
||||
|
||||
if (strcmp(filename, "-") == 0) {
|
||||
input = stdin;
|
||||
} else if ( (input=fopen(filename, "r")) == NULL ) {
|
||||
fprintf(stderr, "%s: Could not open file %s\n", progname, filename);
|
||||
return;
|
||||
}
|
||||
{
|
||||
/* Several complaints have been filed about dc's silence
|
||||
* when a "cd" typo is made. I really wanted to avoid
|
||||
* this mess, but I guess it really should be added...
|
||||
*/
|
||||
#ifndef HAVE_FSTAT
|
||||
/* non-POSIXish system; this code _might_ notice a directory */
|
||||
int c = getc(input);
|
||||
if (c == EOF && ferror(input)) {
|
||||
perror(filename);
|
||||
goto close;
|
||||
}
|
||||
ungetc(c, input);
|
||||
|
||||
#else /* HAVE_FSTAT */
|
||||
/* If HAVE_FSTAT and no S_IS*() macros, it must be a pre-POSIX
|
||||
* Unix-ish system?
|
||||
*/
|
||||
# ifndef S_ISREG
|
||||
# ifdef S_IFREG
|
||||
# define S_ISREG(m) (((m)&S_IFMT)==S_IFREG)
|
||||
# else
|
||||
# define S_ISREG(m) 0
|
||||
# endif
|
||||
# endif
|
||||
# ifndef S_ISCHR
|
||||
# ifdef S_IFCHR
|
||||
# define S_ISCHR(m) (((m)&S_IFMT)==S_IFCHR)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef S_ISFIFO
|
||||
# ifdef S_IFIFO
|
||||
# define S_ISFIFO(m) (((m)&S_IFMT)==S_IFIFO)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef S_ISSOCK
|
||||
# ifdef S_IFSOCK
|
||||
# define S_ISSOCK(m) (((m)&S_IFMT)==S_IFSOCK)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef S_ISDIR
|
||||
# ifdef S_IFDIR
|
||||
# define S_ISDIR(m) (((m)&S_IFMT)==S_IFDIR)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef S_ISBLK
|
||||
# ifdef S_IFBLK
|
||||
# define S_ISBLK(m) (((m)&S_IFMT)==S_IFBLK)
|
||||
# endif
|
||||
# endif
|
||||
struct stat s;
|
||||
if (fstat(fileno(input), &s) == -1) {
|
||||
/* "can't happen" */
|
||||
fprintf(stderr, "%s: Could not fstat file ", progname);
|
||||
perror(filename);
|
||||
goto close;
|
||||
}
|
||||
|
||||
#ifdef S_ISDIR
|
||||
if (S_ISDIR(s.st_mode)) {
|
||||
fprintf(stderr,
|
||||
"%s: Will not attempt to process directory %s\n",
|
||||
progname, filename);
|
||||
goto close;
|
||||
} else
|
||||
#endif
|
||||
#ifdef S_ISBLK
|
||||
if (S_ISBLK(s.st_mode)) {
|
||||
fprintf(stderr,
|
||||
"%s: Will not attempt to process block-special file %s\n",
|
||||
progname, filename);
|
||||
goto close;
|
||||
} else
|
||||
#endif
|
||||
if (!S_ISREG(s.st_mode)
|
||||
# ifdef S_ISCHR
|
||||
/* typically will be /dev/null or some sort of tty */
|
||||
&& !S_ISCHR(s.st_mode)
|
||||
# endif
|
||||
# ifdef S_ISFIFO
|
||||
&& !S_ISFIFO(s.st_mode)
|
||||
# endif
|
||||
# ifdef S_ISSOCK
|
||||
&& !S_ISSOCK(s.st_mode)
|
||||
# endif
|
||||
) {
|
||||
fprintf(stderr,
|
||||
"%s: Will not attempt to process file of unusual type: %s\n",
|
||||
progname, filename);
|
||||
goto close;
|
||||
}
|
||||
#endif /* HAVE_FSTAT */
|
||||
}
|
||||
if (dc_evalfile(input) != DC_SUCCESS)
|
||||
exit(EXIT_FAILURE);
|
||||
close:
|
||||
if (input != stdin)
|
||||
fclose(input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Check to see if there were any output errors; if so, then give
|
||||
* an error message (if stderr is not known to be unhappy), and
|
||||
* ensure that the program exits with an error indication.
|
||||
*/
|
||||
static int
|
||||
flush_okay DC_DECLVOID()
|
||||
{
|
||||
const char *errmsg = NULL;
|
||||
int r = EXIT_SUCCESS;
|
||||
|
||||
if (ferror(stdout))
|
||||
errmsg = "error writing to stdout";
|
||||
else if (fflush(stdout))
|
||||
errmsg = "error flushing stdout";
|
||||
else if (fclose(stdout))
|
||||
errmsg = "error closing stdout";
|
||||
|
||||
if (errmsg) {
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
perror(errmsg);
|
||||
r = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (ferror(stderr) || fclose(stderr))
|
||||
r = EXIT_FAILURE;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
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:f:", long_opts, (int *)0)) != EOF) {
|
||||
switch (c) {
|
||||
case 'e':
|
||||
{ dc_data string = dc_makestring(optarg, strlen(optarg));
|
||||
if (dc_evalstr(&string) != DC_SUCCESS)
|
||||
return flush_okay();
|
||||
dc_free_str(&string.v.string);
|
||||
did_eval = 1;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
try_file(optarg);
|
||||
did_eval = 1;
|
||||
break;
|
||||
case 'h':
|
||||
usage(stdout);
|
||||
return flush_okay();
|
||||
case 'V':
|
||||
show_version();
|
||||
return flush_okay();
|
||||
default:
|
||||
usage(stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
for (; optind < argc; ++optind) {
|
||||
try_file(argv[optind]);
|
||||
did_eval = 1;
|
||||
}
|
||||
if (did_eval == 0) {
|
||||
/* if no -e commands and no command files, then eval stdin */
|
||||
if (dc_evalfile(stdin) != DC_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return flush_okay();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Header file for dc routines
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2008
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DC_DEFS_H
|
||||
#define DC_DEFS_H
|
||||
|
||||
/* 'I' is a command, and bases 17 and 18 are quite
|
||||
* unusual, so we limit ourselves to bases 2 to 16
|
||||
*/
|
||||
#define DC_IBASE_MAX 16
|
||||
|
||||
#define DC_SUCCESS 0
|
||||
#define DC_DOMAIN_ERROR 1
|
||||
#define DC_FAIL 2 /* generic failure */
|
||||
|
||||
|
||||
#ifndef __STDC__
|
||||
# define DC_PROTO(x) ()
|
||||
# define DC_DECLVOID() ()
|
||||
# define DC_DECLARG(arglist) arglist
|
||||
# define DC_DECLSEP ;
|
||||
# define DC_DECLEND ;
|
||||
#else /* __STDC__ */
|
||||
# define DC_PROTO(x) x
|
||||
# define DC_DECLVOID() (void)
|
||||
# define DC_DECLARG(arglist) (
|
||||
# define DC_DECLSEP ,
|
||||
# define DC_DECLEND )
|
||||
#endif /* __STDC__ */
|
||||
|
||||
|
||||
typedef enum {DC_TOSS, DC_KEEP} dc_discard;
|
||||
typedef enum {DC_NONL, DC_WITHNL} dc_newline;
|
||||
|
||||
|
||||
/* type discriminant for dc_data */
|
||||
typedef enum {DC_UNINITIALIZED, DC_NUMBER, DC_STRING} dc_value_type;
|
||||
|
||||
/* only numeric.c knows what dc_num's *really* look like */
|
||||
typedef struct dc_number *dc_num;
|
||||
|
||||
/* only string.c knows what dc_str's *really* look like */
|
||||
typedef struct dc_string *dc_str;
|
||||
|
||||
|
||||
/* except for the two implementation-specific modules, all
|
||||
* dc functions only know of this one generic type of object
|
||||
*/
|
||||
typedef struct {
|
||||
dc_value_type dc_type; /* discriminant for union */
|
||||
union {
|
||||
dc_num number;
|
||||
dc_str string;
|
||||
} v;
|
||||
} dc_data;
|
||||
|
||||
|
||||
/* This is dc's only global variable: */
|
||||
extern const char *progname; /* basename of program invocation */
|
||||
|
||||
#endif /* not DC_DEFS_H */
|
|
@ -0,0 +1,833 @@
|
|||
/*
|
||||
* evaluate the dc language, from a FILE* or a string
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2000, 2003, 2005, 2006, 2008, 2010, 2012-2017
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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 <signal.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include "dc.h"
|
||||
#include "dc-proto.h"
|
||||
|
||||
typedef enum {DC_FALSE, DC_TRUE} dc_boolean;
|
||||
|
||||
typedef enum {
|
||||
DC_OKAY = DC_SUCCESS, /* no further intervention needed for this command */
|
||||
DC_EATONE, /* caller needs to eat the lookahead char */
|
||||
DC_EVALREG, /* caller needs to eval the string named by `peekc' */
|
||||
DC_EVALTOS, /* caller needs to eval the string on top of the stack */
|
||||
DC_QUIT, /* quit out of unwind_depth levels of evaluation */
|
||||
DC_INT, /* caller needs to parse a dc_num from input stream */
|
||||
DC_STR, /* caller needs to parse a dc_str from input stream */
|
||||
DC_SYSTEM, /* caller needs to run a system() on next input line */
|
||||
DC_COMMENT, /* caller needs to skip to the next input line */
|
||||
DC_NEGCMP, /* caller needs to re-call dc_func() with `negcmp' set */
|
||||
|
||||
DC_EOF_ERROR /* unexpected end of input; abort current eval */
|
||||
} dc_status;
|
||||
|
||||
static int dc_ibase=10; /* input base, 2 <= dc_ibase <= DC_IBASE_MAX */
|
||||
static int dc_obase=10; /* output base, 2 <= dc_obase */
|
||||
static int dc_scale=0; /* scale (see user documentaton) */
|
||||
|
||||
/* for Quitting evaluations */
|
||||
static int unwind_depth=0;
|
||||
|
||||
/* for handling SIGINT properly */
|
||||
static volatile sig_atomic_t interrupt_seen=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;
|
||||
|
||||
/* forward reference */
|
||||
static int evalstr(dc_data *string);
|
||||
|
||||
|
||||
/* 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 == '\0')
|
||||
return EOF;
|
||||
return *(const unsigned char *)input_str_string++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* takes a string and evals it; frees the string when done */
|
||||
/* Wrapper around 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 = evalstr(string);
|
||||
if (string->dc_type == DC_STRING)
|
||||
dc_free_str(&string->v.string);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* notice when an interrupt event happens */
|
||||
static void
|
||||
dc_trap_interrupt DC_DECLARG((signo))
|
||||
int signo DC_DECLEND
|
||||
{
|
||||
signal(signo, dc_trap_interrupt);
|
||||
interrupt_seen = 1;
|
||||
}
|
||||
|
||||
|
||||
/* step pointer past next end-of-line (or to end-of-string) */
|
||||
static const char *
|
||||
skip_past_eol DC_DECLARG((strptr, strend))
|
||||
const char *strptr DC_DECLSEP
|
||||
const char *strend DC_DECLEND
|
||||
{
|
||||
const char *p = memchr(strptr, '\n', (size_t)(strend-strptr));
|
||||
if (p != NULL)
|
||||
return p+1;
|
||||
return strend;
|
||||
}
|
||||
|
||||
|
||||
/* dc_func does the grunt work of figuring out what each input
|
||||
* character means; used by both dc_evalstr and dc_evalfile
|
||||
*
|
||||
* c -> the "current" input character under consideration
|
||||
* peekc -> the lookahead input character
|
||||
* negcmp -> negate comparison test (for <,=,> commands)
|
||||
*/
|
||||
static dc_status
|
||||
dc_func DC_DECLARG((c, peekc, negcmp))
|
||||
int c DC_DECLSEP
|
||||
int peekc DC_DECLSEP
|
||||
int negcmp DC_DECLEND
|
||||
{
|
||||
dc_data datum;
|
||||
int tmpint;
|
||||
|
||||
switch (c){
|
||||
case '_': case '.':
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
case '8': case '9': case 'A': case 'B':
|
||||
case 'C': case 'D': case 'E': case 'F':
|
||||
return DC_INT;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
/* standard command separators */
|
||||
break;
|
||||
|
||||
case '+': /* add top two stack elements */
|
||||
dc_binop(dc_add, dc_scale);
|
||||
break;
|
||||
case '-': /* subtract top two stack elements */
|
||||
dc_binop(dc_sub, dc_scale);
|
||||
break;
|
||||
case '*': /* multiply top two stack elements */
|
||||
dc_binop(dc_mul, dc_scale);
|
||||
break;
|
||||
case '/': /* divide top two stack elements */
|
||||
dc_binop(dc_div, dc_scale);
|
||||
break;
|
||||
case '%':
|
||||
/* take the remainder from division of the top two stack elements */
|
||||
dc_binop(dc_rem, dc_scale);
|
||||
break;
|
||||
case '~':
|
||||
/* Do division on the top two stack elements. Return the
|
||||
* quotient as next-to-top of stack and the remainder as
|
||||
* top-of-stack.
|
||||
*/
|
||||
dc_binop2(dc_divrem, dc_scale);
|
||||
break;
|
||||
case '|':
|
||||
/* Consider the top three elements of the stack as (base, exp, mod),
|
||||
* where mod is top-of-stack, exp is next-to-top, and base is
|
||||
* second-from-top. Mod must be non-zero, exp must be non-negative,
|
||||
* and all three must be integers. Push the result of raising
|
||||
* base to the exp power, reduced modulo mod. If we had base in
|
||||
* register b, exp in register e, and mod in register m then this
|
||||
* is conceptually equivalent to "lble^lm%", but it is implemented
|
||||
* in a more efficient manner, and can handle arbritrarily large
|
||||
* values for exp.
|
||||
*/
|
||||
dc_triop(dc_modexp, dc_scale);
|
||||
break;
|
||||
case '^': /* exponientiation of the top two stack elements */
|
||||
dc_binop(dc_exp, dc_scale);
|
||||
break;
|
||||
case '<':
|
||||
/* eval register named by peekc if
|
||||
* less-than holds for top two stack elements
|
||||
*/
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if ( (dc_cmpop() < 0) == (negcmp==0) )
|
||||
return DC_EVALREG;
|
||||
return DC_EATONE;
|
||||
case '=':
|
||||
/* eval register named by peekc if
|
||||
* equal-to holds for top two stack elements
|
||||
*/
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if ( (dc_cmpop() == 0) == (negcmp==0) )
|
||||
return DC_EVALREG;
|
||||
return DC_EATONE;
|
||||
case '>':
|
||||
/* eval register named by peekc if
|
||||
* greater-than holds for top two stack elements
|
||||
*/
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if ( (dc_cmpop() > 0) == (negcmp==0) )
|
||||
return DC_EVALREG;
|
||||
return DC_EATONE;
|
||||
case '?': /* read a line from standard-input and eval it */
|
||||
if (stdin_lookahead != EOF){
|
||||
ungetc(stdin_lookahead, stdin);
|
||||
stdin_lookahead = EOF;
|
||||
}
|
||||
datum = dc_readstring(stdin, '\n', '\n');
|
||||
if (ferror(stdin))
|
||||
return DC_EOF_ERROR;
|
||||
dc_push(datum);
|
||||
return DC_EVALTOS;
|
||||
case '[': /* read to balancing ']' into a dc_str */
|
||||
return DC_STR;
|
||||
case '!': /* read to newline and call system() on resulting string */
|
||||
if (peekc == '<' || peekc == '=' || peekc == '>')
|
||||
return DC_NEGCMP;
|
||||
return DC_SYSTEM;
|
||||
case '#': /* comment; skip remainder of current line */
|
||||
return DC_COMMENT;
|
||||
|
||||
case 'a': /* Convert top of stack to an ascii character. */
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
char tmps;
|
||||
if (datum.dc_type == DC_NUMBER){
|
||||
tmps = (char) dc_num2int(datum.v.number, DC_TOSS);
|
||||
}else if (datum.dc_type == DC_STRING){
|
||||
tmps = *dc_str2charp(datum.v.string);
|
||||
dc_free_str(&datum.v.string);
|
||||
}else{
|
||||
dc_garbage("at top of stack", -1);
|
||||
}
|
||||
dc_push(dc_makestring(&tmps, 1));
|
||||
}
|
||||
break;
|
||||
case 'c': /* clear whole stack */
|
||||
dc_clear_stack();
|
||||
break;
|
||||
case 'd': /* duplicate the datum on the top of stack */
|
||||
if (dc_top_of_stack(&datum) == DC_SUCCESS)
|
||||
dc_push(dc_dup(datum));
|
||||
break;
|
||||
case 'f': /* print list of all stack items */
|
||||
dc_printall(dc_obase);
|
||||
break;
|
||||
case 'i': /* set input base to value on top of stack */
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = 0;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
||||
if (2 <= tmpint && tmpint <= DC_IBASE_MAX)
|
||||
dc_ibase = tmpint;
|
||||
else
|
||||
fprintf(stderr,
|
||||
"%s: input base must be a number \
|
||||
between 2 and %d (inclusive)\n",
|
||||
progname, DC_IBASE_MAX);
|
||||
}
|
||||
break;
|
||||
case 'k': /* set scale to value on top of stack */
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = -1;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
||||
if ( ! (tmpint >= 0) )
|
||||
fprintf(stderr,
|
||||
"%s: scale must be a nonnegative number\n",
|
||||
progname);
|
||||
else
|
||||
dc_scale = tmpint;
|
||||
}
|
||||
break;
|
||||
case 'l': /* "load" -- push value on top of register stack named
|
||||
* by peekc onto top of evaluation stack; does not
|
||||
* modify the register stack
|
||||
*/
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if (dc_register_get(peekc, &datum) == DC_SUCCESS)
|
||||
dc_push(datum);
|
||||
return DC_EATONE;
|
||||
case 'n': /* print the value popped off of top-of-stack;
|
||||
* do not add a trailing newline
|
||||
*/
|
||||
if (dc_pop(&datum) == DC_SUCCESS)
|
||||
dc_print(datum, dc_obase, DC_NONL, DC_TOSS);
|
||||
break;
|
||||
case 'o': /* set output base to value on top of stack */
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = 0;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
||||
if ( ! (tmpint > 1) )
|
||||
fprintf(stderr,
|
||||
"%s: output base must be a number greater than 1\n",
|
||||
progname);
|
||||
else
|
||||
dc_obase = tmpint;
|
||||
}
|
||||
break;
|
||||
case 'p': /* print the datum on the top of stack,
|
||||
* with a trailing newline
|
||||
*/
|
||||
if (dc_top_of_stack(&datum) == DC_SUCCESS)
|
||||
dc_print(datum, dc_obase, DC_WITHNL, DC_KEEP);
|
||||
break;
|
||||
case 'q': /* quit two levels of evaluation, posibly exiting program */
|
||||
unwind_depth = 1; /* the return below is the first level of returns */
|
||||
unwind_noexit = DC_FALSE;
|
||||
return DC_QUIT;
|
||||
case 'r': /* rotate (swap) the top two elements on the stack */
|
||||
dc_stack_rotate(2);
|
||||
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 */
|
||||
return DC_EVALTOS;
|
||||
case 'z': /* push the current stack depth onto the top of stack */
|
||||
dc_push(dc_int2data(dc_tell_stackdepth()));
|
||||
break;
|
||||
|
||||
case 'I': /* push the current input base onto the stack */
|
||||
dc_push(dc_int2data(dc_ibase));
|
||||
break;
|
||||
case 'K': /* push the current scale onto the stack */
|
||||
dc_push(dc_int2data(dc_scale));
|
||||
break;
|
||||
case 'L': /* pop a value off of register stack named by peekc
|
||||
* and push it onto the evaluation stack
|
||||
*/
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if (dc_register_pop(peekc, &datum) == DC_SUCCESS)
|
||||
dc_push(datum);
|
||||
return DC_EATONE;
|
||||
case 'O': /* push the current output base onto the stack */
|
||||
dc_push(dc_int2data(dc_obase));
|
||||
break;
|
||||
case 'P':
|
||||
/* Pop the value off the top of a stack. If it is
|
||||
* a number, dump out the integer portion of its
|
||||
* absolute value as a "base UCHAR_MAX+1" byte stream;
|
||||
* if it is a string, just print it.
|
||||
* In either case, do not append a trailing newline.
|
||||
*/
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
dc_dump_num(datum.v.number, DC_TOSS);
|
||||
else if (datum.dc_type == DC_STRING)
|
||||
dc_out_str(datum.v.string, DC_TOSS);
|
||||
else
|
||||
dc_garbage("at top of stack", -1);
|
||||
}
|
||||
fflush(stdout);
|
||||
break;
|
||||
case 'Q': /* quit out of top-of-stack nested evals;
|
||||
* pops value from stack;
|
||||
* does not exit program (stops short if necessary)
|
||||
*/
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
unwind_depth = 0;
|
||||
unwind_noexit = DC_TRUE;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
unwind_depth = dc_num2int(datum.v.number, DC_TOSS);
|
||||
if (unwind_depth-- > 0)
|
||||
return DC_QUIT;
|
||||
unwind_depth = 0; /* paranoia */
|
||||
fprintf(stderr,
|
||||
"%s: Q command requires a number >= 1\n",
|
||||
progname);
|
||||
}
|
||||
break;
|
||||
case 'R': /* pop a value off of the evaluation stack,;
|
||||
* rotate the top remaining stack elements that many
|
||||
* places forward (negative numbers mean rotate
|
||||
* backward).
|
||||
*/
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = 0;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
||||
dc_stack_rotate(tmpint);
|
||||
}
|
||||
break;
|
||||
case 'S': /* pop a value off of the evaluation stack
|
||||
* and push it onto the register stack named by peekc
|
||||
*/
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if (dc_pop(&datum) == DC_SUCCESS)
|
||||
dc_register_push(peekc, datum);
|
||||
return DC_EATONE;
|
||||
case 'X': /* replace the number on top-of-stack with its scale factor */
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = 0;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_tell_scale(datum.v.number, DC_TOSS);
|
||||
dc_push(dc_int2data(tmpint));
|
||||
}
|
||||
break;
|
||||
case 'Z': /* replace the datum on the top-of-stack with its length */
|
||||
if (dc_pop(&datum) == DC_SUCCESS)
|
||||
dc_push(dc_int2data(dc_tell_length(datum, DC_TOSS)));
|
||||
break;
|
||||
|
||||
case ':': /* store into array */
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = -1;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
if (tmpint < 0)
|
||||
fprintf(stderr,
|
||||
"%s: array index must be a nonnegative integer\n",
|
||||
progname);
|
||||
else
|
||||
dc_array_set(peekc, tmpint, datum);
|
||||
}
|
||||
}
|
||||
return DC_EATONE;
|
||||
case ';': /* retreive from array */
|
||||
if (peekc == EOF)
|
||||
return DC_EOF_ERROR;
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
tmpint = -1;
|
||||
if (datum.dc_type == DC_NUMBER)
|
||||
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
||||
if (tmpint < 0)
|
||||
fprintf(stderr,
|
||||
"%s: array index must be a nonnegative integer\n",
|
||||
progname);
|
||||
else
|
||||
dc_push(dc_array_get(peekc, tmpint));
|
||||
}
|
||||
return DC_EATONE;
|
||||
|
||||
default: /* What did that user mean? */
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
dc_show_id(stdout, c, " unimplemented\n");
|
||||
break;
|
||||
}
|
||||
return DC_OKAY;
|
||||
}
|
||||
|
||||
|
||||
/* takes a string and evals it */
|
||||
static int
|
||||
evalstr DC_DECLARG((string))
|
||||
dc_data *string DC_DECLEND
|
||||
{
|
||||
const char *s;
|
||||
const char *end;
|
||||
const char *p;
|
||||
size_t len;
|
||||
int c;
|
||||
int peekc;
|
||||
int count;
|
||||
int negcmp;
|
||||
int next_negcmp = 0;
|
||||
int tail_depth = 1; /* how much tail recursion is active */
|
||||
dc_data evalstr;
|
||||
|
||||
if (string->dc_type != DC_STRING){
|
||||
fprintf(stderr,
|
||||
"%s: eval called with non-string argument\n",
|
||||
progname);
|
||||
return DC_OKAY;
|
||||
}
|
||||
interrupt_seen = 0;
|
||||
s = dc_str2charp(string->v.string);
|
||||
end = s + dc_strlen(string->v.string);
|
||||
while (s < end && interrupt_seen==0){
|
||||
c = *(const unsigned char *)s++;
|
||||
peekc = EOF;
|
||||
if (s < end)
|
||||
peekc = *(const unsigned char *)s;
|
||||
negcmp = next_negcmp;
|
||||
next_negcmp = 0;
|
||||
switch (dc_func(c, peekc, negcmp)){
|
||||
case DC_OKAY:
|
||||
break;
|
||||
case DC_EATONE:
|
||||
if (peekc != EOF)
|
||||
++s;
|
||||
break;
|
||||
case DC_EVALREG:
|
||||
/*commands which return this guarantee that peekc!=EOF*/
|
||||
++s;
|
||||
if (dc_register_get(peekc, &evalstr) != DC_SUCCESS)
|
||||
break;
|
||||
dc_push(evalstr);
|
||||
/*@fallthrough@*/
|
||||
case DC_EVALTOS:
|
||||
/*skip trailing whitespace to assist tail-recursion detection*/
|
||||
while (s<end && (*s==' '||*s=='\t'||*s=='\n'||*s=='#')){
|
||||
if (*s++ == '#')
|
||||
s = skip_past_eol(s, end);
|
||||
}
|
||||
if (dc_pop(&evalstr) == DC_SUCCESS){
|
||||
if (evalstr.dc_type == DC_NUMBER){
|
||||
dc_push(evalstr);
|
||||
}else if (evalstr.dc_type != DC_STRING){
|
||||
dc_garbage("at top of stack", -1);
|
||||
}else if (s == end){
|
||||
/*handle tail recursion*/
|
||||
dc_free_str(&string->v.string);
|
||||
*string = evalstr;
|
||||
s = dc_str2charp(string->v.string);
|
||||
end = s + dc_strlen(string->v.string);
|
||||
++tail_depth;
|
||||
}else if (dc_eval_and_free_str(&evalstr) == DC_QUIT){
|
||||
if (unwind_depth > 0){
|
||||
--unwind_depth;
|
||||
return DC_QUIT;
|
||||
}
|
||||
return DC_OKAY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DC_QUIT:
|
||||
if (unwind_depth >= tail_depth){
|
||||
unwind_depth -= tail_depth;
|
||||
return DC_QUIT;
|
||||
}
|
||||
/*adjust tail recursion accounting and continue*/
|
||||
tail_depth -= unwind_depth;
|
||||
break;
|
||||
|
||||
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 = (size_t) (p - s);
|
||||
dc_push(dc_makestring(s, (count==0 ? len-1 : len)));
|
||||
s = p;
|
||||
break;
|
||||
case DC_SYSTEM:
|
||||
s = dc_system(s);
|
||||
break;
|
||||
case DC_COMMENT:
|
||||
s = skip_past_eol(s, end);
|
||||
break;
|
||||
case DC_NEGCMP:
|
||||
next_negcmp = 1;
|
||||
break;
|
||||
|
||||
case DC_EOF_ERROR:
|
||||
if (ferror(stdin)) {
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
perror("error reading stdin");
|
||||
return DC_FAIL;
|
||||
}
|
||||
fprintf(stderr, "%s: unexpected EOS\n", progname);
|
||||
return DC_OKAY;
|
||||
}
|
||||
}
|
||||
return DC_OKAY;
|
||||
}
|
||||
|
||||
/* wrapper around evalstr, to handle top-level QUIT requests correctly*/
|
||||
int
|
||||
dc_evalstr(dc_data *string)
|
||||
{
|
||||
switch (evalstr(string)) {
|
||||
case DC_OKAY:
|
||||
return DC_SUCCESS;
|
||||
case DC_QUIT:
|
||||
if (unwind_noexit != DC_TRUE)
|
||||
return DC_FAIL;
|
||||
return DC_SUCCESS;
|
||||
default:
|
||||
return DC_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This is the main function of the whole DC program.
|
||||
* Reads the file described by fp, calls dc_func to do
|
||||
* the dirty work, and takes care of dc_func's shortcomings.
|
||||
*/
|
||||
int
|
||||
dc_evalfile DC_DECLARG((fp))
|
||||
FILE *fp DC_DECLEND
|
||||
{
|
||||
int c;
|
||||
int peekc;
|
||||
int negcmp;
|
||||
int next_negcmp = 0;
|
||||
typedef void (*handler_t)(int);
|
||||
handler_t sigint_handler = dc_trap_interrupt;
|
||||
handler_t sigint_default = signal(SIGINT, SIG_IGN);
|
||||
dc_data datum;
|
||||
|
||||
/* Signals are awkward: we want to allow interactive users
|
||||
* to break out of long running macros, but otherwise we
|
||||
* prefer that SIGINT not be given any special treatment.
|
||||
* Sometimes "no special treatment" means to continue to
|
||||
* *ignore* the signal, but usually it means to kill the program.
|
||||
*/
|
||||
signal(SIGINT, sigint_default);
|
||||
#ifdef HAVE_UNISTD_H
|
||||
/* don't trap SIGINT if we can tell that we are not reading from a tty */
|
||||
if ( ! isatty(fileno(fp)) )
|
||||
sigint_handler = sigint_default;
|
||||
#endif
|
||||
|
||||
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;
|
||||
/*
|
||||
* In the switch(), cases which naturally update peekc
|
||||
* (unconditionally) do not have to update or reference
|
||||
* stdin_lookahead; other functions use the predicate:
|
||||
* stdin_lookahead != peekc && fp == stdin
|
||||
* to recognize the case where:
|
||||
* a) stdin_lookahead == EOF (stdin and peekc are not in sync)
|
||||
* b) peekc != EOF (resync is possible)
|
||||
* c) fp == stdin (resync is relevant)
|
||||
* The whole stdin_lookahead complication arises because the
|
||||
* '?' command may be invoked from an arbritrarily deeply
|
||||
* nested dc_evalstr(), '?' reads exclusively from stdin,
|
||||
* and this winds up making peekc invalid when fp==stdin.
|
||||
*/
|
||||
negcmp = next_negcmp;
|
||||
next_negcmp = 0;
|
||||
signal(SIGINT, sigint_handler);
|
||||
switch (dc_func(c, peekc, negcmp)){
|
||||
case DC_OKAY:
|
||||
if (stdin_lookahead != peekc && fp == stdin)
|
||||
peekc = getc(fp);
|
||||
break;
|
||||
case DC_EATONE:
|
||||
peekc = getc(fp);
|
||||
break;
|
||||
case DC_EVALREG:
|
||||
/*commands which send us here shall guarantee that peekc!=EOF*/
|
||||
c = peekc;
|
||||
peekc = getc(fp);
|
||||
stdin_lookahead = peekc;
|
||||
if (dc_register_get(c, &datum) != DC_SUCCESS)
|
||||
break;
|
||||
dc_push(datum);
|
||||
/*@fallthrough@*/
|
||||
case DC_EVALTOS:
|
||||
if (stdin_lookahead != peekc && fp == stdin)
|
||||
peekc = getc(fp);
|
||||
if (dc_pop(&datum) == DC_SUCCESS){
|
||||
if (datum.dc_type == DC_NUMBER){
|
||||
dc_push(datum);
|
||||
}else if (datum.dc_type == DC_STRING){
|
||||
if (dc_eval_and_free_str(&datum) == DC_QUIT){
|
||||
if (unwind_noexit != DC_TRUE)
|
||||
goto reset_and_exit_quit;
|
||||
fprintf(stderr, "%s: Q command argument exceeded \
|
||||
string execution depth\n", progname);
|
||||
}
|
||||
}else{
|
||||
dc_garbage("at top of stack", -1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DC_QUIT:
|
||||
if (unwind_noexit != DC_TRUE)
|
||||
goto reset_and_exit_quit;
|
||||
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));
|
||||
if (ferror(fp))
|
||||
goto error_fail;
|
||||
break;
|
||||
case DC_STR:
|
||||
ungetc(peekc, fp);
|
||||
datum = dc_readstring(fp, '[', ']');
|
||||
if (ferror(fp))
|
||||
goto error_fail;
|
||||
dc_push(datum);
|
||||
peekc = getc(fp);
|
||||
break;
|
||||
case DC_SYSTEM:
|
||||
ungetc(peekc, fp);
|
||||
datum = dc_readstring(fp, '\n', '\n');
|
||||
if (ferror(fp))
|
||||
goto error_fail;
|
||||
(void)dc_system(dc_str2charp(datum.v.string));
|
||||
dc_free_str(&datum.v.string);
|
||||
peekc = getc(fp);
|
||||
break;
|
||||
case DC_COMMENT:
|
||||
while (peekc!=EOF && peekc!='\n')
|
||||
peekc = getc(fp);
|
||||
if (peekc != EOF)
|
||||
peekc = getc(fp);
|
||||
break;
|
||||
case DC_NEGCMP:
|
||||
next_negcmp = 1;
|
||||
break;
|
||||
|
||||
case DC_EOF_ERROR:
|
||||
if (ferror(fp))
|
||||
goto error_fail;
|
||||
fprintf(stderr, "%s: unexpected EOF\n", progname);
|
||||
goto reset_and_exit_fail;
|
||||
}
|
||||
|
||||
if (interrupt_seen)
|
||||
fprintf(stderr, "\nInterrupt!\n");
|
||||
interrupt_seen = 0;
|
||||
signal(SIGINT, sigint_default);
|
||||
}
|
||||
if (!ferror(fp))
|
||||
goto reset_and_exit_success;
|
||||
|
||||
error_fail:
|
||||
fprintf(stderr, "%s: ", progname);
|
||||
perror("error reading input");
|
||||
return DC_FAIL;
|
||||
reset_and_exit_quit:
|
||||
reset_and_exit_fail:
|
||||
signal(SIGINT, sigint_default);
|
||||
return DC_FAIL;
|
||||
reset_and_exit_success:
|
||||
signal(SIGINT, sigint_default);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* misc. functions for the "dc" Desk Calculator language.
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2000, 2006, 2008, 2013
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This module contains miscellaneous functions that have no
|
||||
* special knowledge of any private data structures.
|
||||
* They could each be moved to their own separate modules,
|
||||
* but are aggregated here as a matter of convenience.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#ifndef isgraph
|
||||
# ifndef HAVE_ISGRAPH
|
||||
# define isgraph isprint
|
||||
# endif
|
||||
#endif
|
||||
#include <getopt.h>
|
||||
#include "dc.h"
|
||||
#include "dc-proto.h"
|
||||
|
||||
#ifndef EXIT_FAILURE /* C89 <stdlib.h> */
|
||||
# define EXIT_FAILURE 1
|
||||
#endif
|
||||
|
||||
|
||||
/* print an "out of memory" diagnostic and exit program */
|
||||
void
|
||||
dc_memfail DC_DECLVOID()
|
||||
{
|
||||
fprintf(stderr, "%s: out of memory\n", progname);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* malloc or die */
|
||||
void *
|
||||
dc_malloc DC_DECLARG((len))
|
||||
size_t len DC_DECLEND
|
||||
{
|
||||
void *result = malloc(len);
|
||||
|
||||
if (result == NULL)
|
||||
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", (unsigned int) id, id, suffix);
|
||||
else
|
||||
fprintf(fp, "%#o%s", (unsigned int) 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 != NULL) {
|
||||
len = (size_t) (p - s);
|
||||
tmpstr = dc_malloc(len + 1);
|
||||
strncpy(tmpstr, s, len);
|
||||
tmpstr[len] = '\0';
|
||||
system(tmpstr);
|
||||
free(tmpstr);
|
||||
return p + 1;
|
||||
}
|
||||
system(s);
|
||||
return s + strlen(s);
|
||||
}
|
||||
|
||||
|
||||
/* print out the indicated value */
|
||||
void
|
||||
dc_print DC_DECLARG((value, obase, newline_p, discard_p))
|
||||
dc_data value DC_DECLSEP
|
||||
int obase DC_DECLSEP
|
||||
dc_newline newline_p DC_DECLSEP
|
||||
dc_discard discard_p DC_DECLEND
|
||||
{
|
||||
if (value.dc_type == DC_NUMBER) {
|
||||
dc_out_num(value.v.number, obase, discard_p);
|
||||
} else if (value.dc_type == DC_STRING) {
|
||||
dc_out_str(value.v.string, discard_p);
|
||||
} else {
|
||||
dc_garbage("in data being printed", -1);
|
||||
}
|
||||
if (newline_p == DC_WITHNL)
|
||||
putchar ('\n');
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,671 @@
|
|||
/*
|
||||
* interface dc to the bc numeric routines
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2000, 2005, 2008, 2013, 2017
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* make all the header files see that these are really the same thing;
|
||||
* this is acceptable because everywhere else dc_number is just referenced
|
||||
* as a pointer-to-incomplete-structure type
|
||||
*/
|
||||
#define dc_number bc_struct
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#ifndef UCHAR_MAX
|
||||
# define UCHAR_MAX ((unsigned char)~0)
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
# include <errno.h>
|
||||
#else
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#include "number.h"
|
||||
#include "dc.h"
|
||||
#include "dc-proto.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__-0 >= 7)
|
||||
# define ATTRIB(x) __attribute__(x)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef ATTRIB
|
||||
# define ATTRIB(x)
|
||||
#endif
|
||||
|
||||
/* Forward prototype */
|
||||
static void out_char (int);
|
||||
|
||||
/* there is no POSIX standard for dc, so we'll take the GNU definitions */
|
||||
int std_only = FALSE;
|
||||
|
||||
/* convert an opaque dc_num into a real bc_num */
|
||||
/* by a freak accident, these are now no-op mappings,
|
||||
* but leave the notation here in case that changes later
|
||||
* */
|
||||
#define CastNum(x) (x)
|
||||
#define CastNumPtr(x) (x)
|
||||
|
||||
/* add two dc_nums, place into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_add DC_DECLARG((a, b, kscale, result))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale ATTRIB((unused)) DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
bc_add(CastNum(a), CastNum(b), CastNumPtr(result), 0);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* subtract two dc_nums, place into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_sub DC_DECLARG((a, b, kscale, result))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale ATTRIB((unused)) DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
bc_sub(CastNum(a), CastNum(b), CastNumPtr(result), 0);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* multiply two dc_nums, place into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_mul DC_DECLARG((a, b, kscale, result))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
bc_multiply(CastNum(a), CastNum(b), CastNumPtr(result), kscale);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* divide two dc_nums, place into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_div DC_DECLARG((a, b, kscale, result))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
if (bc_divide(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){
|
||||
fprintf(stderr, "%s: divide by zero\n", progname);
|
||||
return DC_DOMAIN_ERROR;
|
||||
}
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* divide two dc_nums, place quotient into *quotient and remainder
|
||||
* into *remainder;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_divrem DC_DECLARG((a, b, kscale, quotient, remainder))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *quotient DC_DECLSEP
|
||||
dc_num *remainder DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(quotient));
|
||||
bc_init_num(CastNumPtr(remainder));
|
||||
if (bc_divmod(CastNum(a), CastNum(b),
|
||||
CastNumPtr(quotient), CastNumPtr(remainder), kscale)){
|
||||
fprintf(stderr, "%s: divide by zero\n", progname);
|
||||
return DC_DOMAIN_ERROR;
|
||||
}
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* place the reminder of dividing a by b into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_rem DC_DECLARG((a, b, kscale, result))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
if (bc_modulo(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){
|
||||
fprintf(stderr, "%s: remainder by zero\n", progname);
|
||||
return DC_DOMAIN_ERROR;
|
||||
}
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
dc_modexp DC_DECLARG((base, expo, mod, kscale, result))
|
||||
dc_num base DC_DECLSEP
|
||||
dc_num expo DC_DECLSEP
|
||||
dc_num mod DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
if (bc_raisemod(CastNum(base), CastNum(expo), CastNum(mod),
|
||||
CastNumPtr(result), kscale)){
|
||||
if (bc_is_zero(CastNum(mod)))
|
||||
fprintf(stderr, "%s: remainder by zero\n", progname);
|
||||
return DC_DOMAIN_ERROR;
|
||||
}
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* place the result of exponentiationg a by b into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_exp DC_DECLARG((a, b, kscale, result))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_init_num(CastNumPtr(result));
|
||||
bc_raise(CastNum(a), CastNum(b), CastNumPtr(result), kscale);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* take the square root of the value, place into *result;
|
||||
* return DC_SUCCESS on success, DC_DOMAIN_ERROR on domain error
|
||||
*/
|
||||
int
|
||||
dc_sqrt DC_DECLARG((value, kscale, result))
|
||||
dc_num value DC_DECLSEP
|
||||
int kscale DC_DECLSEP
|
||||
dc_num *result DC_DECLEND
|
||||
{
|
||||
bc_num tmp;
|
||||
|
||||
tmp = bc_copy_num(CastNum(value));
|
||||
if (!bc_sqrt(&tmp, kscale)){
|
||||
fprintf(stderr, "%s: square root of negative number\n", progname);
|
||||
bc_free_num(&tmp);
|
||||
return DC_DOMAIN_ERROR;
|
||||
}
|
||||
*(CastNumPtr(result)) = tmp;
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* compare dc_nums a and b;
|
||||
* return a negative value if a < b;
|
||||
* return a positive value if a > b;
|
||||
* return zero value if a == b
|
||||
*/
|
||||
int
|
||||
dc_compare DC_DECLARG((a, b))
|
||||
dc_num a DC_DECLSEP
|
||||
dc_num b DC_DECLEND
|
||||
{
|
||||
return bc_compare(CastNum(a), CastNum(b));
|
||||
}
|
||||
|
||||
/* attempt to convert a dc_num to its corresponding int value
|
||||
* If discard_p is DC_TOSS then deallocate the value after use.
|
||||
*/
|
||||
int
|
||||
dc_num2int DC_DECLARG((value, discard_p))
|
||||
dc_num value DC_DECLSEP
|
||||
dc_discard discard_p DC_DECLEND
|
||||
{
|
||||
long result;
|
||||
|
||||
result = bc_num2long(CastNum(value));
|
||||
if (result == 0 && !bc_is_zero(CastNum(value))) {
|
||||
fprintf(stderr, "%s: value overflows simple integer; punting...\n",
|
||||
progname);
|
||||
result = -1; /* more appropriate for dc's purposes */
|
||||
}
|
||||
if (discard_p == DC_TOSS)
|
||||
dc_free_num(&value);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
/* convert a C integer value into a dc_num */
|
||||
/* For convenience of the caller, package the dc_num
|
||||
* into a dc_data result.
|
||||
*/
|
||||
dc_data
|
||||
dc_int2data DC_DECLARG((value))
|
||||
int value DC_DECLEND
|
||||
{
|
||||
dc_data result;
|
||||
|
||||
bc_init_num(CastNumPtr(&result.v.number));
|
||||
bc_int2num(CastNumPtr(&result.v.number), value);
|
||||
result.dc_type = DC_NUMBER;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* get a dc_num from some input stream;
|
||||
* input is a function which knows how to read the desired input stream
|
||||
* ibase is the input base (2<=ibase<=DC_IBASE_MAX)
|
||||
* *readahead will be set to the readahead character consumed while
|
||||
* looking for the end-of-number
|
||||
*/
|
||||
/* For convenience of the caller, package the dc_num
|
||||
* into a dc_data result.
|
||||
*/
|
||||
dc_data
|
||||
dc_getnum DC_DECLARG((input, ibase, readahead))
|
||||
int (*input) DC_PROTO((void)) DC_DECLSEP
|
||||
int ibase DC_DECLSEP
|
||||
int *readahead DC_DECLEND
|
||||
{
|
||||
bc_num base;
|
||||
bc_num result;
|
||||
bc_num build;
|
||||
bc_num tmp;
|
||||
bc_num divisor;
|
||||
dc_data full_result;
|
||||
int negative = 0;
|
||||
int digit;
|
||||
int decimal;
|
||||
int c;
|
||||
|
||||
bc_init_num(&tmp);
|
||||
bc_init_num(&build);
|
||||
bc_init_num(&base);
|
||||
result = bc_copy_num(_zero_);
|
||||
bc_int2num(&base, ibase);
|
||||
c = (*input)();
|
||||
while (isspace(c))
|
||||
c = (*input)();
|
||||
if (c == '_' || c == '-'){
|
||||
negative = c;
|
||||
c = (*input)();
|
||||
}else if (c == '+'){
|
||||
c = (*input)();
|
||||
}
|
||||
while (isspace(c))
|
||||
c = (*input)();
|
||||
for (;;){
|
||||
if (isdigit(c))
|
||||
digit = c - '0';
|
||||
else if ('A' <= c && c <= 'F')
|
||||
digit = 10 + c - 'A';
|
||||
else
|
||||
break;
|
||||
c = (*input)();
|
||||
bc_int2num(&tmp, digit);
|
||||
bc_multiply(result, base, &result, 0);
|
||||
bc_add(result, tmp, &result, 0);
|
||||
}
|
||||
if (c == '.'){
|
||||
bc_free_num(&build);
|
||||
bc_free_num(&tmp);
|
||||
divisor = bc_copy_num(_one_);
|
||||
build = bc_copy_num(_zero_);
|
||||
decimal = 0;
|
||||
for (;;){
|
||||
c = (*input)();
|
||||
if (isdigit(c))
|
||||
digit = c - '0';
|
||||
else if ('A' <= c && c <= 'F')
|
||||
digit = 10 + c - 'A';
|
||||
else
|
||||
break;
|
||||
bc_int2num(&tmp, digit);
|
||||
bc_multiply(build, base, &build, 0);
|
||||
bc_add(build, tmp, &build, 0);
|
||||
bc_multiply(divisor, base, &divisor, 0);
|
||||
++decimal;
|
||||
}
|
||||
bc_divide(build, divisor, &build, decimal);
|
||||
bc_add(result, build, &result, 0);
|
||||
}
|
||||
/* Final work. */
|
||||
if (negative)
|
||||
bc_sub(_zero_, result, &result, 0);
|
||||
|
||||
bc_free_num(&tmp);
|
||||
bc_free_num(&build);
|
||||
bc_free_num(&base);
|
||||
if (readahead)
|
||||
*readahead = c;
|
||||
*CastNumPtr(&full_result.v.number) = result;
|
||||
full_result.dc_type = DC_NUMBER;
|
||||
return full_result;
|
||||
}
|
||||
|
||||
|
||||
/* Return the "length" of the number, ignoring *all* leading zeros,
|
||||
* (including those to the right of the radix point!)
|
||||
*/
|
||||
int
|
||||
dc_numlen DC_DECLARG((value))
|
||||
dc_num value DC_DECLEND
|
||||
{
|
||||
/* XXX warning: unholy coziness with the internals of a bc_num! */
|
||||
bc_num num = CastNum(value);
|
||||
char *p = num->n_value;
|
||||
int i = num->n_len + num->n_scale;
|
||||
|
||||
while (1<i && *p=='\0')
|
||||
--i, ++p;
|
||||
return i;
|
||||
}
|
||||
|
||||
/* return the scale factor of the passed dc_num
|
||||
* If discard_p is DC_TOSS then deallocate the value after use.
|
||||
*/
|
||||
int
|
||||
dc_tell_scale DC_DECLARG((value, discard_p))
|
||||
dc_num value DC_DECLSEP
|
||||
dc_discard discard_p DC_DECLEND
|
||||
{
|
||||
int kscale;
|
||||
|
||||
kscale = CastNum(value)->n_scale;
|
||||
if (discard_p == DC_TOSS)
|
||||
dc_free_num(&value);
|
||||
return kscale;
|
||||
}
|
||||
|
||||
|
||||
/* initialize the math subsystem */
|
||||
void
|
||||
dc_math_init DC_DECLVOID()
|
||||
{
|
||||
bc_init_numbers();
|
||||
}
|
||||
|
||||
/* print out a dc_num in output base obase to stdout;
|
||||
* if discard_p is DC_TOSS then deallocate the value after use
|
||||
*/
|
||||
void
|
||||
dc_out_num DC_DECLARG((value, obase, discard_p))
|
||||
dc_num value DC_DECLSEP
|
||||
int obase DC_DECLSEP
|
||||
dc_discard discard_p DC_DECLEND
|
||||
{
|
||||
out_char('\0'); /* clear the column counter */
|
||||
bc_out_num(CastNum(value), obase, out_char, 0);
|
||||
if (discard_p == DC_TOSS)
|
||||
dc_free_num(&value);
|
||||
}
|
||||
|
||||
/* dump out the absolute value of the integer part of a
|
||||
* dc_num as a byte stream, without any line wrapping;
|
||||
* if discard_p is DC_TOSS then deallocate the value after use
|
||||
*/
|
||||
void
|
||||
dc_dump_num DC_DECLARG((dcvalue, discard_p))
|
||||
dc_num dcvalue DC_DECLSEP
|
||||
dc_discard discard_p DC_DECLEND
|
||||
{
|
||||
struct digit_stack { int digit; struct digit_stack *link;};
|
||||
struct digit_stack *top_of_stack = NULL;
|
||||
struct digit_stack *cur;
|
||||
struct digit_stack *next;
|
||||
bc_num value;
|
||||
bc_num obase;
|
||||
bc_num digit;
|
||||
|
||||
bc_init_num(&value);
|
||||
bc_init_num(&obase);
|
||||
bc_init_num(&digit);
|
||||
|
||||
/* we only handle the integer portion: */
|
||||
bc_divide(CastNum(dcvalue), _one_, &value, 0);
|
||||
/* we only handle the absolute value: */
|
||||
value->n_sign = PLUS;
|
||||
/* we're done with the dcvalue parameter: */
|
||||
if (discard_p == DC_TOSS)
|
||||
dc_free_num(&dcvalue);
|
||||
|
||||
bc_int2num(&obase, 1+UCHAR_MAX);
|
||||
do {
|
||||
(void) bc_divmod(value, obase, &value, &digit, 0);
|
||||
cur = dc_malloc(sizeof *cur);
|
||||
cur->digit = (int)bc_num2long(digit);
|
||||
cur->link = top_of_stack;
|
||||
top_of_stack = cur;
|
||||
} while (!bc_is_zero(value));
|
||||
|
||||
for (cur=top_of_stack; cur; cur=next) {
|
||||
putchar(cur->digit);
|
||||
next = cur->link;
|
||||
free(cur);
|
||||
}
|
||||
|
||||
bc_free_num(&digit);
|
||||
bc_free_num(&obase);
|
||||
bc_free_num(&value);
|
||||
}
|
||||
|
||||
/* deallocate an instance of a dc_num */
|
||||
void
|
||||
dc_free_num DC_DECLARG((value))
|
||||
dc_num *value DC_DECLEND
|
||||
{
|
||||
bc_free_num(CastNumPtr(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_STDARG_H
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRTOL
|
||||
/* Maintain some of the error checking of a real strtol() on
|
||||
* ancient systems that lack one, but punting on the niceties
|
||||
* of supporting bases other than 10 and overflow checking.
|
||||
*/
|
||||
long
|
||||
strtol(const char *s, char **end, int base)
|
||||
{
|
||||
int sign = 1;
|
||||
long result = 0;
|
||||
|
||||
for (;; ++s) {
|
||||
if (*s == '-')
|
||||
sign = -sign;
|
||||
else if (*s != '+' && !isspace(*(const unsigned char *)s))
|
||||
break;
|
||||
}
|
||||
while (isdigit(*(const unsigned char *)s))
|
||||
result = 10*result + (*s++ - '0');
|
||||
*end = s;
|
||||
return result * sign;
|
||||
}
|
||||
#endif /*!HAVE_STRTOL*/
|
||||
|
||||
|
||||
static int out_col = 0;
|
||||
static int line_max = -1; /* negative means "need to check environment" */
|
||||
#define DEFAULT_LINE_MAX 70
|
||||
|
||||
static void
|
||||
set_line_max_from_environment(void)
|
||||
{
|
||||
const char *env_line_len = getenv("DC_LINE_LENGTH");
|
||||
line_max = DEFAULT_LINE_MAX;
|
||||
errno = 0;
|
||||
if (env_line_len) {
|
||||
char *endptr;
|
||||
long proposed_line_len = strtol(env_line_len, &endptr, 0);
|
||||
line_max = (int)proposed_line_len;
|
||||
|
||||
/* silently enforce sanity */
|
||||
while (isspace(*(const unsigned char *)endptr))
|
||||
++endptr;
|
||||
if (*endptr || errno || line_max != proposed_line_len
|
||||
|| line_max < 0 || line_max == 1)
|
||||
line_max = DEFAULT_LINE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output routines: Write a character CH to the standard output.
|
||||
It keeps track of the number of characters output and may
|
||||
break the output with a "\<cr>". */
|
||||
|
||||
static void
|
||||
out_char (ch)
|
||||
int ch;
|
||||
{
|
||||
if (ch == '\0') {
|
||||
out_col = 0;
|
||||
} else {
|
||||
if (line_max < 0)
|
||||
set_line_max_from_environment();
|
||||
if (++out_col >= line_max && line_max != 0) {
|
||||
putchar ('\\');
|
||||
putchar ('\n');
|
||||
out_col = 1;
|
||||
}
|
||||
putchar(ch);
|
||||
}
|
||||
}
|
||||
|
||||
/* Malloc could not get enough memory. */
|
||||
|
||||
void
|
||||
out_of_memory()
|
||||
{
|
||||
dc_memfail();
|
||||
}
|
||||
|
||||
/* Runtime error --- will print a message and stop the machine. */
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
#ifdef __STDC__
|
||||
void
|
||||
rt_error (char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
rt_error (mesg)
|
||||
char *mesg;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
rt_error (mesg, va_alist)
|
||||
char *mesg;
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fprintf (stderr, "Runtime error: ");
|
||||
#ifdef HAVE_STDARG_H
|
||||
va_start (args, mesg);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
vfprintf (stderr, mesg, args);
|
||||
va_end (args);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
/* A runtime warning tells of some action taken by the processor that
|
||||
may change the program execution but was not enough of a problem
|
||||
to stop the execution. */
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
#ifdef __STDC__
|
||||
void
|
||||
rt_warn (char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
rt_warn (mesg)
|
||||
char *mesg;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
rt_warn (mesg, va_alist)
|
||||
char *mesg;
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fprintf (stderr, "Runtime warning: ");
|
||||
#ifdef HAVE_STDARG_H
|
||||
va_start (args, mesg);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
vfprintf (stderr, mesg, args);
|
||||
va_end (args);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* implement stack functions for dc
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2000, 2005, 2006, 2008, 2012, 2016
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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 implementation suffices: */
|
||||
struct dc_list {
|
||||
dc_data value;
|
||||
struct dc_array *array; /* opaque */
|
||||
struct dc_list *link;
|
||||
};
|
||||
typedef struct dc_list dc_list;
|
||||
|
||||
/* the anonymous evaluation stack */
|
||||
static dc_list *dc_stack=NULL;
|
||||
|
||||
/* the named register stacks */
|
||||
typedef dc_list *dc_listp;
|
||||
static dc_listp dc_register[DC_REGCOUNT];
|
||||
|
||||
|
||||
/* allocate a new dc_list item */
|
||||
static dc_list *
|
||||
dc_alloc DC_DECLVOID()
|
||||
{
|
||||
dc_list *result;
|
||||
|
||||
result = dc_malloc(sizeof *result);
|
||||
result->value.dc_type = DC_UNINITIALIZED;
|
||||
result->array = NULL;
|
||||
result->link = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* check that there are two numbers on top of the stack,
|
||||
* then call op with the popped numbers. Construct a dc_data
|
||||
* value from the dc_num returned by op and push it
|
||||
* on the stack.
|
||||
* If the op call doesn't return DC_SUCCESS, then leave the stack
|
||||
* unmodified.
|
||||
*/
|
||||
void
|
||||
dc_binop DC_DECLARG((op, kscale))
|
||||
int (*op)DC_PROTO((dc_num, dc_num, int, dc_num *)) DC_DECLSEP
|
||||
int kscale DC_DECLEND
|
||||
{
|
||||
dc_data a;
|
||||
dc_data b;
|
||||
dc_data r;
|
||||
|
||||
if (dc_stack == NULL || dc_stack->link == NULL){
|
||||
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 == NULL || dc_stack->link == NULL){
|
||||
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 == NULL || dc_stack->link == NULL){
|
||||
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 == NULL
|
||||
|| dc_stack->link == NULL
|
||||
|| dc_stack->link->link == NULL){
|
||||
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!=NULL; n=t){
|
||||
t = n->link;
|
||||
if (n->value.dc_type == DC_NUMBER)
|
||||
dc_free_num(&n->value.v.number);
|
||||
else if (n->value.dc_type == DC_STRING)
|
||||
dc_free_str(&n->value.v.string);
|
||||
else
|
||||
dc_garbage("in stack", -1);
|
||||
dc_array_free(n->array);
|
||||
free(n);
|
||||
}
|
||||
dc_stack = NULL;
|
||||
}
|
||||
|
||||
/* push a value onto the evaluation stack */
|
||||
void
|
||||
dc_push DC_DECLARG((value))
|
||||
dc_data value DC_DECLEND
|
||||
{
|
||||
dc_list *n = dc_alloc();
|
||||
|
||||
if (value.dc_type!=DC_NUMBER && value.dc_type!=DC_STRING)
|
||||
dc_garbage("in data being pushed", -1);
|
||||
n->value = value;
|
||||
n->link = dc_stack;
|
||||
dc_stack = n;
|
||||
}
|
||||
|
||||
/* push a value onto the named register stack */
|
||||
void
|
||||
dc_register_push DC_DECLARG((stackid, value))
|
||||
int stackid DC_DECLSEP
|
||||
dc_data value DC_DECLEND
|
||||
{
|
||||
dc_list *n = dc_alloc();
|
||||
|
||||
stackid = regmap(stackid);
|
||||
n->value = value;
|
||||
n->link = dc_register[stackid];
|
||||
dc_register[stackid] = n;
|
||||
}
|
||||
|
||||
/* set *result to the value on the top of the evaluation stack */
|
||||
/* The caller is responsible for duplicating the value if it
|
||||
* is to be maintained as anything more than a transient identity.
|
||||
*
|
||||
* DC_FAIL is returned if the stack is empty (and *result unchanged),
|
||||
* DC_SUCCESS is returned otherwise
|
||||
*/
|
||||
int
|
||||
dc_top_of_stack DC_DECLARG((result))
|
||||
dc_data *result DC_DECLEND
|
||||
{
|
||||
if (dc_stack == NULL){
|
||||
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,
|
||||
* or 0 (zero) if the stack is empty */
|
||||
/*
|
||||
* DC_FAIL is returned if an internal bug is detected
|
||||
* 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==NULL){
|
||||
*result = dc_int2data(0);
|
||||
}else if (r->value.dc_type==DC_UNINITIALIZED){
|
||||
fprintf(stderr, "%s: BUG: register ", progname);
|
||||
dc_show_id(stderr, regid, " exists but is uninitialized?\n");
|
||||
return DC_FAIL;
|
||||
}else{
|
||||
*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 == NULL)
|
||||
dc_register[regid] = dc_alloc();
|
||||
else if (r->value.dc_type == DC_NUMBER)
|
||||
dc_free_num(&r->value.v.number);
|
||||
else if (r->value.dc_type == DC_STRING)
|
||||
dc_free_str(&r->value.v.string);
|
||||
else if (r->value.dc_type == DC_UNINITIALIZED)
|
||||
;
|
||||
else
|
||||
dc_garbage("", regid);
|
||||
dc_register[regid]->value = value;
|
||||
}
|
||||
|
||||
/* pop from the evaluation stack
|
||||
*
|
||||
* DC_FAIL is returned if the stack is empty (and *result unchanged),
|
||||
* DC_SUCCESS is returned otherwise
|
||||
*/
|
||||
int
|
||||
dc_pop DC_DECLARG((result))
|
||||
dc_data *result DC_DECLEND
|
||||
{
|
||||
dc_list *r;
|
||||
|
||||
r = dc_stack;
|
||||
if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){
|
||||
Empty_Stack;
|
||||
return DC_FAIL;
|
||||
}
|
||||
if (r->value.dc_type!=DC_NUMBER && r->value.dc_type!=DC_STRING)
|
||||
dc_garbage("at top of stack", -1);
|
||||
*result = r->value;
|
||||
dc_stack = r->link;
|
||||
dc_array_free(r->array);
|
||||
free(r);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
/* pop from the named register stack
|
||||
*
|
||||
* DC_FAIL is returned if the named stack is empty (and *result unchanged),
|
||||
* DC_SUCCESS is returned otherwise
|
||||
*/
|
||||
int
|
||||
dc_register_pop DC_DECLARG((stackid, result))
|
||||
int stackid DC_DECLSEP
|
||||
dc_data *result DC_DECLEND
|
||||
{
|
||||
dc_list *r;
|
||||
|
||||
stackid = regmap(stackid);
|
||||
r = dc_register[stackid];
|
||||
if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){
|
||||
fprintf(stderr, "%s: stack register ", progname);
|
||||
dc_show_id(stderr, stackid, " is empty\n");
|
||||
return DC_FAIL;
|
||||
}
|
||||
if (r->value.dc_type!=DC_NUMBER && r->value.dc_type!=DC_STRING)
|
||||
dc_garbage(" stack", stackid);
|
||||
*result = r->value;
|
||||
dc_register[stackid] = r->link;
|
||||
dc_array_free(r->array);
|
||||
free(r);
|
||||
return DC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* cyclically rotate the "n" topmost elements of the stack;
|
||||
* negative "n" rotates forward (topomost element becomes n-th deep)
|
||||
* positive "n" rotates backward (topmost element becomes 2nd deep)
|
||||
*
|
||||
* If stack depth is less than "n", whole stack is rotated
|
||||
* (without raising an error).
|
||||
*/
|
||||
void
|
||||
dc_stack_rotate(int n)
|
||||
{
|
||||
dc_list *p; /* becomes bottom of sub-stack */
|
||||
dc_list *r; /* predecessor of "p" */
|
||||
int absn = n<0 ? -n : n;
|
||||
|
||||
/* always do nothing for empty stack or degenerate rotation depth */
|
||||
if (!dc_stack || absn < 2)
|
||||
return;
|
||||
/* find bottom of rotation sub-stack */
|
||||
r = NULL;
|
||||
for (p=dc_stack; p->link && --absn>0; p=p->link)
|
||||
r = p;
|
||||
/* if stack has only one element, treat rotation as no-op */
|
||||
if (!r)
|
||||
return;
|
||||
/* do the rotation, in appropriate direction */
|
||||
if (n > 0) {
|
||||
r->link = p->link;
|
||||
p->link = dc_stack;
|
||||
dc_stack = p;
|
||||
} else {
|
||||
dc_list *new_tos = dc_stack->link;
|
||||
dc_stack->link = p->link;
|
||||
p->link = dc_stack;
|
||||
dc_stack = new_tos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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!=NULL; n=n->link)
|
||||
++depth;
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
/* return the length of the indicated data value;
|
||||
* if discard_p is DC_TOSS, the deallocate the value when done
|
||||
*
|
||||
* The definition of a datum's length is deligated to the
|
||||
* appropriate module.
|
||||
*/
|
||||
int
|
||||
dc_tell_length DC_DECLARG((value, discard_p))
|
||||
dc_data value DC_DECLSEP
|
||||
dc_discard discard_p DC_DECLEND
|
||||
{
|
||||
int length;
|
||||
|
||||
if (value.dc_type == DC_NUMBER){
|
||||
length = dc_numlen(value.v.number);
|
||||
if (discard_p == DC_TOSS)
|
||||
dc_free_num(&value.v.number);
|
||||
} else if (value.dc_type == DC_STRING) {
|
||||
length = (int) dc_strlen(value.v.string);
|
||||
if (discard_p == DC_TOSS)
|
||||
dc_free_str(&value.v.string);
|
||||
} else {
|
||||
dc_garbage("in tell_length", -1);
|
||||
/*NOTREACHED*/
|
||||
length = 0; /*just to suppress spurious compiler warnings*/
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* print out all of the values on the evaluation stack */
|
||||
void
|
||||
dc_printall DC_DECLARG((obase))
|
||||
int obase DC_DECLEND
|
||||
{
|
||||
dc_list *n;
|
||||
|
||||
for (n=dc_stack; n!=NULL; n=n->link)
|
||||
dc_print(n->value, obase, DC_WITHNL, DC_KEEP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* get the current array head for the named array */
|
||||
struct dc_array *
|
||||
dc_get_stacked_array DC_DECLARG((array_id))
|
||||
int array_id DC_DECLEND
|
||||
{
|
||||
dc_list *r = dc_register[regmap(array_id)];
|
||||
return r == NULL ? NULL : r->array;
|
||||
}
|
||||
|
||||
/* set the current array head for the named array */
|
||||
void
|
||||
dc_set_stacked_array DC_DECLARG((array_id, new_head))
|
||||
int array_id DC_DECLSEP
|
||||
struct dc_array *new_head DC_DECLEND
|
||||
{
|
||||
dc_list *r;
|
||||
|
||||
array_id = regmap(array_id);
|
||||
r = dc_register[array_id];
|
||||
if (r == NULL)
|
||||
r = dc_register[array_id] = dc_alloc();
|
||||
r->array = new_head;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* implement string functions for dc
|
||||
*
|
||||
* Copyright (C) 1994, 1997, 1998, 2006, 2008, 2013
|
||||
* 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 3, 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* 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.
|
||||
* Free the value after use if discard_flag is set.
|
||||
*/
|
||||
void
|
||||
dc_out_str DC_DECLARG((value, discard_flag))
|
||||
dc_str value DC_DECLSEP
|
||||
dc_discard discard_flag DC_DECLEND
|
||||
{
|
||||
fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
|
||||
if (discard_flag == DC_TOSS)
|
||||
dc_free_str(&value);
|
||||
}
|
||||
|
||||
/* make a copy of a string (base s, length len)
|
||||
* into a dc_str value; return a dc_data result
|
||||
* with this value
|
||||
*/
|
||||
dc_data
|
||||
dc_makestring DC_DECLARG((s, len))
|
||||
const char *s DC_DECLSEP
|
||||
size_t len DC_DECLEND
|
||||
{
|
||||
dc_data result;
|
||||
struct dc_string *string;
|
||||
|
||||
string = dc_malloc(sizeof *string);
|
||||
string->s_ptr = dc_malloc(len+1);
|
||||
memcpy(string->s_ptr, s, len);
|
||||
string->s_ptr[len] = '\0'; /* nul terminated for those who need it */
|
||||
string->s_len = len;
|
||||
string->s_refs = 1;
|
||||
result.v.string = string;
|
||||
result.dc_type = DC_STRING;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read a dc_str value from FILE *fp;
|
||||
* if ldelim == rdelim, then read until a ldelim char or EOF is reached;
|
||||
* if ldelim != rdelim, then read until a matching rdelim for the
|
||||
* (already eaten) first ldelim is read.
|
||||
* Return a dc_data result with the dc_str value as its contents.
|
||||
*/
|
||||
dc_data
|
||||
dc_readstring DC_DECLARG((fp, ldelim, rdelim))
|
||||
FILE *fp DC_DECLSEP
|
||||
int ldelim DC_DECLSEP
|
||||
int rdelim DC_DECLEND
|
||||
{
|
||||
static char *line_buf = NULL; /* a buffer to build the string in */
|
||||
static size_t buflen = 0; /* the current size of line_buf */
|
||||
int depth=1;
|
||||
int c;
|
||||
char *p;
|
||||
const char *end;
|
||||
|
||||
if (line_buf == NULL){
|
||||
/* initial buflen should be large enough to handle most cases */
|
||||
buflen = (size_t) 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 == NULL)
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: C
|
||||
* tab-width: 4
|
||||
* End:
|
||||
* vi: set ts=4 :
|
||||
*/
|
|
@ -0,0 +1,791 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2013-05-30.07; # UTC
|
||||
|
||||
# Copyright (C) 1999-2013 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,11 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
info_TEXINFOS = bc.texi dc.texi
|
||||
MAKEINFO = makeinfo --no-split
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
dist_man_MANS = bc.1 dc.1
|
||||
|
||||
bc.dvi bc.pdf bc.html $(srcdir)/bc.info \
|
||||
dc.dvi dc.pdf dc.html $(srcdir)/dc.info : texi-ver.incl
|
|
@ -0,0 +1,768 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = doc
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(srcdir)/texi-ver.incl.in texinfo.tex $(dist_man_MANS)
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES = texi-ver.incl
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
AM_V_DVIPS = $(am__v_DVIPS_@AM_V@)
|
||||
am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@)
|
||||
am__v_DVIPS_0 = @echo " DVIPS " $@;
|
||||
am__v_DVIPS_1 =
|
||||
AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@)
|
||||
am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@)
|
||||
am__v_MAKEINFO_0 = @echo " MAKEINFO" $@;
|
||||
am__v_MAKEINFO_1 =
|
||||
AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@)
|
||||
am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@)
|
||||
am__v_INFOHTML_0 = @echo " INFOHTML" $@;
|
||||
am__v_INFOHTML_1 =
|
||||
AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@)
|
||||
am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@)
|
||||
am__v_TEXI2DVI_0 = @echo " TEXI2DVI" $@;
|
||||
am__v_TEXI2DVI_1 =
|
||||
AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@)
|
||||
am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@)
|
||||
am__v_TEXI2PDF_0 = @echo " TEXI2PDF" $@;
|
||||
am__v_TEXI2PDF_1 =
|
||||
AM_V_texinfo = $(am__v_texinfo_@AM_V@)
|
||||
am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@)
|
||||
am__v_texinfo_0 = -q
|
||||
am__v_texinfo_1 =
|
||||
AM_V_texidevnull = $(am__v_texidevnull_@AM_V@)
|
||||
am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@)
|
||||
am__v_texidevnull_0 = > /dev/null
|
||||
am__v_texidevnull_1 =
|
||||
INFO_DEPS = $(srcdir)/bc.info $(srcdir)/dc.info
|
||||
am__TEXINFO_TEX_DIR = $(srcdir)
|
||||
DVIS = bc.dvi dc.dvi
|
||||
PDFS = bc.pdf dc.pdf
|
||||
PSS = bc.ps dc.ps
|
||||
HTMLS = bc.html dc.html
|
||||
TEXINFOS = bc.texi dc.texi
|
||||
TEXI2DVI = texi2dvi
|
||||
TEXI2PDF = $(TEXI2DVI) --pdf --batch
|
||||
MAKEINFOHTML = $(MAKEINFO) --html
|
||||
AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS)
|
||||
DVIPS = dvips
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
*) f=$$p;; \
|
||||
esac;
|
||||
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
|
||||
am__install_max = 40
|
||||
am__nobase_strip_setup = \
|
||||
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
|
||||
am__nobase_strip = \
|
||||
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
|
||||
am__nobase_list = $(am__nobase_strip_setup); \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
|
||||
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
|
||||
if (++n[$$2] == $(am__install_max)) \
|
||||
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
|
||||
END { for (dir in files) print dir, files[dir] }'
|
||||
am__base_list = \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
|
||||
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
|
||||
am__uninstall_files_from_dir = { \
|
||||
test -z "$$files" \
|
||||
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|
||||
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|
||||
$(am__cd) "$$dir" && rm -f $$files; }; \
|
||||
}
|
||||
man1dir = $(mandir)/man1
|
||||
NROFF = nroff
|
||||
MANS = $(dist_man_MANS)
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BC_VERSION = @BC_VERSION@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DC_VERSION = @DC_VERSION@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = makeinfo --no-split
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
READLINELIB = @READLINELIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
YACC = @YACC@
|
||||
YFLAGS = @YFLAGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
info_TEXINFOS = bc.texi dc.texi
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
dist_man_MANS = bc.1 dc.1
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .dvi .html .info .pdf .ps .texi
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu doc/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
texi-ver.incl: $(top_builddir)/config.status $(srcdir)/texi-ver.incl.in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
|
||||
|
||||
.texi.info:
|
||||
$(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \
|
||||
am__cwd=`pwd` && $(am__cd) $(srcdir) && \
|
||||
rm -rf $$backupdir && mkdir $$backupdir && \
|
||||
if ($(MAKEINFO) --version) >/dev/null 2>&1; then \
|
||||
for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
|
||||
if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
|
||||
done; \
|
||||
else :; fi && \
|
||||
cd "$$am__cwd"; \
|
||||
if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
||||
-o $@ $<; \
|
||||
then \
|
||||
rc=0; \
|
||||
$(am__cd) $(srcdir); \
|
||||
else \
|
||||
rc=$$?; \
|
||||
$(am__cd) $(srcdir) && \
|
||||
$$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
|
||||
fi; \
|
||||
rm -rf $$backupdir; exit $$rc
|
||||
|
||||
.texi.dvi:
|
||||
$(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||
$(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \
|
||||
$<
|
||||
|
||||
.texi.pdf:
|
||||
$(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
|
||||
$(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \
|
||||
$<
|
||||
|
||||
.texi.html:
|
||||
$(AM_V_MAKEINFO)rm -rf $(@:.html=.htp)
|
||||
$(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
|
||||
-o $(@:.html=.htp) $<; \
|
||||
then \
|
||||
rm -rf $@ && mv $(@:.html=.htp) $@; \
|
||||
else \
|
||||
rm -rf $(@:.html=.htp); exit 1; \
|
||||
fi
|
||||
$(srcdir)/bc.info: bc.texi
|
||||
bc.dvi: bc.texi
|
||||
bc.pdf: bc.texi
|
||||
bc.html: bc.texi
|
||||
$(srcdir)/dc.info: dc.texi
|
||||
dc.dvi: dc.texi
|
||||
dc.pdf: dc.texi
|
||||
dc.html: dc.texi
|
||||
.dvi.ps:
|
||||
$(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
|
||||
$(DVIPS) $(AM_V_texinfo) -o $@ $<
|
||||
|
||||
uninstall-dvi-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(DVIS)'; test -n "$(dvidir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(dvidir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-html-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(HTMLS)'; test -n "$(htmldir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \
|
||||
rm -rf "$(DESTDIR)$(htmldir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-info-am:
|
||||
@$(PRE_UNINSTALL)
|
||||
@if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \
|
||||
list='$(INFO_DEPS)'; \
|
||||
for file in $$list; do \
|
||||
relfile=`echo "$$file" | sed 's|^.*/||'`; \
|
||||
echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \
|
||||
if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \
|
||||
then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \
|
||||
done; \
|
||||
else :; fi
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(INFO_DEPS)'; \
|
||||
for file in $$list; do \
|
||||
relfile=`echo "$$file" | sed 's|^.*/||'`; \
|
||||
relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
(if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \
|
||||
echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \
|
||||
rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
|
||||
else :; fi); \
|
||||
done
|
||||
|
||||
uninstall-pdf-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(pdfdir)/$$f"; \
|
||||
done
|
||||
|
||||
uninstall-ps-am:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(PSS)'; test -n "$(psdir)" || list=; \
|
||||
for p in $$list; do \
|
||||
$(am__strip_dir) \
|
||||
echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(psdir)/$$f"; \
|
||||
done
|
||||
|
||||
dist-info: $(INFO_DEPS)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(INFO_DEPS)'; \
|
||||
for base in $$list; do \
|
||||
case $$base in \
|
||||
$(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
esac; \
|
||||
if test -f $$base; then d=.; else d=$(srcdir); fi; \
|
||||
base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \
|
||||
if test -f $$file; then \
|
||||
relfile=`expr "$$file" : "$$d/\(.*\)"`; \
|
||||
test -f "$(distdir)/$$relfile" || \
|
||||
cp -p $$file "$(distdir)/$$relfile"; \
|
||||
else :; fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
mostlyclean-aminfo:
|
||||
-rm -rf bc.t2d bc.t2p dc.t2d dc.t2p
|
||||
|
||||
clean-aminfo:
|
||||
-test -z "bc.dvi bc.pdf bc.ps bc.html dc.dvi dc.pdf dc.ps dc.html" \
|
||||
|| rm -rf bc.dvi bc.pdf bc.ps bc.html dc.dvi dc.pdf dc.ps dc.html
|
||||
|
||||
maintainer-clean-aminfo:
|
||||
@list='$(INFO_DEPS)'; for i in $$list; do \
|
||||
i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
|
||||
rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
|
||||
done
|
||||
install-man1: $(dist_man_MANS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list1=''; \
|
||||
list2='$(dist_man_MANS)'; \
|
||||
test -n "$(man1dir)" \
|
||||
&& test -n "`echo $$list1$$list2`" \
|
||||
|| exit 0; \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
|
||||
{ for i in $$list1; do echo "$$i"; done; \
|
||||
if test -n "$$list2"; then \
|
||||
for i in $$list2; do echo "$$i"; done \
|
||||
| sed -n '/\.1[a-z]*$$/p'; \
|
||||
fi; \
|
||||
} | while read p; do \
|
||||
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; echo "$$p"; \
|
||||
done | \
|
||||
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
|
||||
sed 'N;N;s,\n, ,g' | { \
|
||||
list=; while read file base inst; do \
|
||||
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
|
||||
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
|
||||
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
|
||||
fi; \
|
||||
done; \
|
||||
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
|
||||
done; }
|
||||
|
||||
uninstall-man1:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list=''; test -n "$(man1dir)" || exit 0; \
|
||||
files=`{ for i in $$list; do echo "$$i"; done; \
|
||||
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
|
||||
sed -n '/\.1[a-z]*$$/p'; \
|
||||
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
|
||||
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
|
||||
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$(top_distdir)" distdir="$(distdir)" \
|
||||
dist-info
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(INFO_DEPS) $(MANS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-aminfo clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am: $(DVIS)
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am: $(HTMLS)
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am: $(INFO_DEPS)
|
||||
|
||||
install-data-am: install-info-am install-man
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am: $(DVIS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(DVIS)'; test -n "$(dvidir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \
|
||||
done
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am: $(HTMLS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
$(am__strip_dir) \
|
||||
d2=$$d$$p; \
|
||||
if test -d "$$d2"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
|
||||
echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \
|
||||
$(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \
|
||||
else \
|
||||
list2="$$list2 $$d2"; \
|
||||
fi; \
|
||||
done; \
|
||||
test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
|
||||
done; }
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am: $(INFO_DEPS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \
|
||||
fi; \
|
||||
for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
esac; \
|
||||
if test -f $$file; then d=.; else d=$(srcdir); fi; \
|
||||
file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \
|
||||
for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \
|
||||
$$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \
|
||||
if test -f $$ifile; then \
|
||||
echo "$$ifile"; \
|
||||
else : ; fi; \
|
||||
done; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done
|
||||
@$(POST_INSTALL)
|
||||
@if $(am__can_run_installinfo); then \
|
||||
list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
|
||||
for file in $$list; do \
|
||||
relfile=`echo "$$file" | sed 's|^.*/||'`; \
|
||||
echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\
|
||||
install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
|
||||
done; \
|
||||
else : ; fi
|
||||
install-man: install-man1
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am: $(PDFS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am: $(PSS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(PSS)'; test -n "$(psdir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
echo "$$d$$p"; \
|
||||
done | $(am__base_list) | \
|
||||
while read files; do \
|
||||
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \
|
||||
$(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-aminfo \
|
||||
maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-aminfo mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am: $(PDFS)
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am: $(PSS)
|
||||
|
||||
uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
|
||||
uninstall-man uninstall-pdf-am uninstall-ps-am
|
||||
|
||||
uninstall-man: uninstall-man1
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-aminfo clean-generic \
|
||||
cscopelist-am ctags-am dist-info distclean distclean-generic \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-man1 install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-aminfo \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-aminfo \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \
|
||||
uninstall-am uninstall-dvi-am uninstall-html-am \
|
||||
uninstall-info-am uninstall-man uninstall-man1 \
|
||||
uninstall-pdf-am uninstall-ps-am
|
||||
|
||||
|
||||
bc.dvi bc.pdf bc.html $(srcdir)/bc.info \
|
||||
dc.dvi dc.pdf dc.html $(srcdir)/dc.info : texi-ver.incl
|
||||
|
||||
# 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:
|
|
@ -0,0 +1,823 @@
|
|||
.\"
|
||||
.\" bc.1 - the *roff document processor source for the bc manual
|
||||
.\"
|
||||
.\" This file is part of GNU bc.
|
||||
.\" Copyright (C) 1991-1994, 1997, 2000, 2003, 2006, 2017 Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation; either version 2 of the License , or
|
||||
.\" (at your option) any later version.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
.\" GNU General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License
|
||||
.\" along with this program; see the file COPYING. If not, write to:
|
||||
.\" The Free Software Foundation, Inc.
|
||||
.\" 51 Franklin Street, Fifth Floor
|
||||
.\" Boston, MA 02110-1301 USA
|
||||
.\"
|
||||
.\" You may contact the author by:
|
||||
.\" e-mail: philnelson@acm.org
|
||||
.\" us-mail: Philip A. Nelson
|
||||
.\" Computer Science Department, 9062
|
||||
.\" Western Washington University
|
||||
.\" Bellingham, WA 98226-9062
|
||||
.\"
|
||||
.\"
|
||||
.TH bc 1 "2006-06-11" "GNU Project"
|
||||
.SH NAME
|
||||
bc - An arbitrary precision calculator language
|
||||
.SH SYNTAX
|
||||
\fBbc\fR [ \fB-hlwsqv\fR ] [long-options] [ \fI file ...\fR ]
|
||||
.SH DESCRIPTION
|
||||
\fBbc\fR is a language that supports arbitrary precision numbers
|
||||
with interactive execution of statements. There are some similarities
|
||||
in the syntax to the C programming language.
|
||||
A standard math library is available by command line option.
|
||||
If requested, the math library is defined before processing any files.
|
||||
\fBbc\fR starts by processing code from all the files listed
|
||||
on the command line in the order listed. After all files have been
|
||||
processed, \fBbc\fR reads from the standard input. All code is
|
||||
executed as it is read. (If a file contains a command to halt the
|
||||
processor, \fBbc\fR will never read from the standard input.)
|
||||
.PP
|
||||
This version of \fBbc\fR contains several extensions beyond
|
||||
traditional \fBbc\fR implementations and the POSIX draft standard.
|
||||
Command line options can cause these extensions to print a warning
|
||||
or to be rejected. This
|
||||
document describes the language accepted by this processor.
|
||||
Extensions will be identified as such.
|
||||
.SS OPTIONS
|
||||
.IP "-h, --help"
|
||||
Print the usage and exit.
|
||||
.IP "-i, --interactive"
|
||||
Force interactive mode.
|
||||
.IP "-l, --mathlib"
|
||||
Define the standard math library.
|
||||
.IP "-w, --warn"
|
||||
Give warnings for extensions to POSIX \fBbc\fR.
|
||||
.IP "-s, --standard"
|
||||
Process exactly the POSIX \fBbc\fR language.
|
||||
.IP "-q, --quiet"
|
||||
Do not print the normal GNU bc welcome.
|
||||
.IP "-v, --version"
|
||||
Print the version number and copyright and quit.
|
||||
.SS NUMBERS
|
||||
The most basic element in \fBbc\fR is the number. Numbers are
|
||||
arbitrary precision numbers. This precision is both in the integer
|
||||
part and the fractional part. All numbers are represented internally
|
||||
in decimal and all computation is done in decimal. (This version
|
||||
truncates results from divide and multiply operations.) There are two
|
||||
attributes of numbers, the length and the scale. The length is the
|
||||
total number of decimal digits used by \fBbc\fR to represent 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 36. (Bases greater than
|
||||
16 are an extension.) Assigning a value outside this range to
|
||||
\fBibase\fR will result in a value of 2 or 36. Input numbers may
|
||||
contain the characters 0-9 and A-Z. (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 \fBZZZ\fR always be the largest
|
||||
3 digit number of the input base.
|
||||
.PP
|
||||
Full expressions are similar to many other high level languages.
|
||||
Since there is only one kind of number, there are no rules for mixing
|
||||
types. Instead, there are rules on the scale of expressions. Every
|
||||
expression has a scale. This is derived from the scale of original
|
||||
numbers, the operation performed and in many cases, the value of the
|
||||
variable \fBscale\fR. Legal values of the variable \fBscale\fR are
|
||||
0 to the maximum number representable by a C integer.
|
||||
.PP
|
||||
In the following descriptions of legal expressions, "expr" refers to a
|
||||
complete expression and "var" refers to a simple or an array variable.
|
||||
A simple variable is just a
|
||||
.RS
|
||||
\fIname\fR
|
||||
.RE
|
||||
and an array variable is specified as
|
||||
.RS
|
||||
\fIname\fR[\fIexpr\fR]
|
||||
.RE
|
||||
Unless specifically
|
||||
mentioned the scale of the result is the maximum scale of the
|
||||
expressions involved.
|
||||
.IP "- expr"
|
||||
The result is the negation of the expression.
|
||||
.IP "++ var"
|
||||
The variable is incremented by one and the new value is the result of
|
||||
the expression.
|
||||
.IP "-- var"
|
||||
The variable
|
||||
is decremented by one and the new value is the result of the
|
||||
expression.
|
||||
.IP "var ++"
|
||||
The result of the expression is the value of
|
||||
the variable and then the variable is incremented by one.
|
||||
.IP "var --"
|
||||
The result of the expression is the value of the variable and then
|
||||
the variable is decremented by one.
|
||||
.IP "expr + expr"
|
||||
The result of the expression is the sum of the two expressions.
|
||||
.IP "expr - expr"
|
||||
The result of the expression is the difference of the two expressions.
|
||||
.IP "expr * expr"
|
||||
The result of the expression is the product of the two expressions.
|
||||
.IP "expr / expr"
|
||||
The result of the expression is the quotient of the two expressions.
|
||||
The scale of the result is the value of the variable \fBscale\fR.
|
||||
.IP "expr % expr"
|
||||
The result of the expression is the "remainder" and it is computed in the
|
||||
following way. To compute a%b, first a/b is computed to \fBscale\fR
|
||||
digits. That result is used to compute a-(a/b)*b to the scale of the
|
||||
maximum of \fBscale\fR+scale(b) and scale(a). If \fBscale\fR is set
|
||||
to zero and both expressions are integers this expression is the
|
||||
integer remainder function.
|
||||
.IP "expr ^ expr"
|
||||
The result of the expression is the value of the first raised to the
|
||||
second. The second expression must be an integer. (If the second
|
||||
expression is not an integer, a warning is generated and the
|
||||
expression is truncated to get an integer value.) The scale of the
|
||||
result is \fBscale\fR if the exponent is negative. If the exponent
|
||||
is positive the scale of the result is the minimum of the scale of the
|
||||
first expression times the value of the exponent and the maximum of
|
||||
\fBscale\fR and the scale of the first expression. (e.g. scale(a^b)
|
||||
= min(scale(a)*b, max( \fBscale,\fR scale(a))).) It should be noted
|
||||
that expr^0 will always return the value of 1.
|
||||
.IP "( expr )"
|
||||
This alters the standard precedence to force the evaluation of the
|
||||
expression.
|
||||
.IP "var = expr"
|
||||
The variable is assigned the value of the expression.
|
||||
.IP "var <op>= expr"
|
||||
This is equivalent to "var = var <op> expr" with the exception that
|
||||
the "var" part is evaluated only once. This can make a difference if
|
||||
"var" is an array.
|
||||
.PP
|
||||
Relational expressions are a special kind of expression
|
||||
that always evaluate to 0 or 1, 0 if the relation is false and 1 if
|
||||
the relation is true. These may appear in any legal expression.
|
||||
(POSIX bc requires that relational expressions are used only in if,
|
||||
while, and for statements and that only one relational test may be
|
||||
done in them.) The relational operators are
|
||||
.IP "expr1 < expr2"
|
||||
The result is 1 if expr1 is strictly less than expr2.
|
||||
.IP "expr1 <= expr2"
|
||||
The result is 1 if expr1 is less than or equal to expr2.
|
||||
.IP "expr1 > expr2"
|
||||
The result is 1 if expr1 is strictly greater than expr2.
|
||||
.IP "expr1 >= expr2"
|
||||
The result is 1 if expr1 is greater than or equal to expr2.
|
||||
.IP "expr1 == expr2"
|
||||
The result is 1 if expr1 is equal to expr2.
|
||||
.IP "expr1 != expr2"
|
||||
The result is 1 if expr1 is not equal to expr2.
|
||||
.PP
|
||||
Boolean operations are also legal. (POSIX \fBbc\fR does NOT have
|
||||
boolean operations). The result of all boolean operations are 0 and 1
|
||||
(for false and true) as in relational expressions. The boolean
|
||||
operators are:
|
||||
.IP "!expr"
|
||||
The result is 1 if expr is 0.
|
||||
.IP "expr && expr"
|
||||
The result is 1 if both expressions are non-zero.
|
||||
.IP "expr || expr"
|
||||
The result is 1 if either expression is non-zero.
|
||||
.PP
|
||||
The expression precedence is as follows: (lowest to highest)
|
||||
.nf
|
||||
.RS
|
||||
|| operator, left associative
|
||||
&& operator, left associative
|
||||
! operator, nonassociative
|
||||
Relational operators, left associative
|
||||
Assignment operator, right associative
|
||||
+ and - operators, left associative
|
||||
*, / and % operators, left associative
|
||||
^ operator, right associative
|
||||
unary - operator, nonassociative
|
||||
++ and -- operators, nonassociative
|
||||
.RE
|
||||
.fi
|
||||
.PP
|
||||
This precedence was chosen so that POSIX compliant \fBbc\fR programs
|
||||
will run correctly. This will cause the use of the relational and
|
||||
logical operators to have some unusual behavior when used with
|
||||
assignment expressions. Consider the expression:
|
||||
.RS
|
||||
a = 3 < 5
|
||||
.RE
|
||||
.PP
|
||||
Most C programmers would assume this would assign the result of "3 <
|
||||
5" (the value 1) to the variable "a". What this does in \fBbc\fR is
|
||||
assign the value 3 to the variable "a" and then compare 3 to 5. It is
|
||||
best to use parenthesis when using relational and logical operators
|
||||
with the assignment operators.
|
||||
.PP
|
||||
There are a few more special expressions that are provided in \fBbc\fR.
|
||||
These have to do with user defined functions and standard
|
||||
functions. They all appear as "\fIname\fB(\fIparameters\fB)\fR".
|
||||
See the section on functions for user defined functions. The standard
|
||||
functions are:
|
||||
.IP "length ( expression )"
|
||||
The value of the length function is the number of significant digits in the
|
||||
expression.
|
||||
.IP "read ( )"
|
||||
The read function (an extension) will read a number from the standard
|
||||
input, regardless of where the function occurs. Beware, this can
|
||||
cause problems with the mixing of data and program in the standard input.
|
||||
The best use for this function is in a previously written program that
|
||||
needs input from the user, but never allows program code to be input
|
||||
from the user. The value of the read function is the number read from
|
||||
the standard input using the current value of the variable
|
||||
\fBibase\fR for the conversion base.
|
||||
.IP "scale ( expression )"
|
||||
The value of the scale function is the number of digits after the decimal
|
||||
point in the expression.
|
||||
.IP "sqrt ( expression )"
|
||||
The value of the sqrt function is the square root of the expression. If
|
||||
the expression is negative, a run time error is generated.
|
||||
.SS STATEMENTS
|
||||
Statements (as in most algebraic languages) provide the sequencing of
|
||||
expression evaluation. In \fBbc\fR statements are executed "as soon
|
||||
as possible." Execution happens when a newline in encountered and
|
||||
there is one or more complete statements. Due to this immediate
|
||||
execution, newlines are very important in \fBbc\fR. In fact, both a
|
||||
semicolon and a newline are used as statement separators. An
|
||||
improperly placed newline will cause a syntax error. Because newlines
|
||||
are statement separators, it is possible to hide a newline by using
|
||||
the backslash character. The sequence "\e<nl>", where <nl> is the
|
||||
newline appears to \fBbc\fR as whitespace instead of a newline. A
|
||||
statement list is a series of statements separated by semicolons and
|
||||
newlines. The following is a list of \fBbc\fR statements and what
|
||||
they do: (Things enclosed in brackets ([]) are optional parts of the
|
||||
statement.)
|
||||
.IP "expression"
|
||||
This statement does one of two things. If the expression starts with
|
||||
"<variable> <assignment> ...", it is considered to be an assignment
|
||||
statement. If the expression is not an assignment statement, the
|
||||
expression is evaluated and printed to the output. After the number
|
||||
is printed, a newline is printed. For example, "a=1" is an assignment
|
||||
statement and "(a=1)" is an expression that has an embedded
|
||||
assignment. All numbers that are printed are printed in the base
|
||||
specified by the variable \fBobase\fR. The legal values for \fB
|
||||
obase\fR are 2 through BC_BASE_MAX. (See the section LIMITS.) For
|
||||
bases 2 through 16, the usual method of writing numbers is used. For
|
||||
bases greater than 16, \fBbc\fR uses a multi-character digit method
|
||||
of printing the numbers where each higher base digit is printed as a
|
||||
base 10 number. The multi-character digits are separated by spaces.
|
||||
Each digit contains the number of characters required to represent the
|
||||
base ten value of "obase-1". Since numbers are of arbitrary
|
||||
precision, some numbers may not be printable on a single output line.
|
||||
These long numbers will be split across lines using the "\e" as the
|
||||
last character on a line. The maximum number of characters printed
|
||||
per line is 70. Due to the interactive nature of \fBbc\fR, printing
|
||||
a number causes the side effect of assigning the printed value to the
|
||||
special variable \fBlast\fR. This allows the user to recover the
|
||||
last value printed without having to retype the expression that
|
||||
printed the number. Assigning to \fBlast\fR is legal and will
|
||||
overwrite the last printed value with the assigned value. The newly
|
||||
assigned value will remain until the next number is printed or another
|
||||
value is assigned to \fBlast\fR. (Some installations may allow the
|
||||
use of a single period (.) which is not part of a number as a short
|
||||
hand notation for for \fBlast\fR.)
|
||||
.IP "string"
|
||||
The string is printed to the output. Strings start with a double quote
|
||||
character and contain all characters until the next double quote character.
|
||||
All characters are take literally, including any newline. No newline
|
||||
character is printed after the string.
|
||||
.IP "\fBprint\fR list"
|
||||
The print statement (an extension) provides another method of output.
|
||||
The "list" is a list of strings and expressions separated by commas.
|
||||
Each string or expression is printed in the order of the list. No
|
||||
terminating newline is printed. Expressions are evaluated and their
|
||||
value is printed and assigned to the variable \fBlast\fR. Strings
|
||||
in the print statement are printed to the output and may contain
|
||||
special characters. Special characters start with the backslash
|
||||
character (\e). The special characters recognized by \fBbc\fR are
|
||||
"a" (alert or bell), "b" (backspace), "f" (form feed), "n" (newline),
|
||||
"r" (carriage return), "q" (double quote), "t" (tab), and "\e" (backslash).
|
||||
Any other character following the backslash will be ignored.
|
||||
.IP "{ statement_list }"
|
||||
This is the compound statement. It allows multiple statements to be
|
||||
grouped together for execution.
|
||||
.IP "\fBif\fR ( expression ) statement1 [\fBelse\fR statement2]"
|
||||
The if statement evaluates the expression and executes statement1 or
|
||||
statement2 depending on the value of the expression. If the expression
|
||||
is non-zero, statement1 is executed. If statement2 is present and
|
||||
the value of the expression is 0, then statement2 is executed. (The
|
||||
else clause is an extension.)
|
||||
.IP "\fBwhile\fR ( expression ) statement"
|
||||
The while statement will execute the statement while the expression
|
||||
is non-zero. It evaluates the expression before each execution of
|
||||
the statement. Termination of the loop is caused by a zero
|
||||
expression value or the execution of a break statement.
|
||||
.IP "\fBfor\fR ( [expression1] ; [expression2] ; [expression3] ) statement"
|
||||
The for statement controls repeated execution of the statement.
|
||||
Expression1 is evaluated before the loop. Expression2 is evaluated
|
||||
before each execution of the statement. If it is non-zero, the statement
|
||||
is evaluated. If it is zero, the loop is terminated. After each
|
||||
execution of the statement, expression3 is evaluated before the reevaluation
|
||||
of expression2. If expression1 or expression3 are missing, nothing is
|
||||
evaluated at the point they would be evaluated.
|
||||
If expression2 is missing, it is the same as substituting
|
||||
the value 1 for expression2. (The optional expressions are an
|
||||
extension. POSIX \fBbc\fR requires all three expressions.)
|
||||
The following is equivalent code for the for statement:
|
||||
.nf
|
||||
.RS
|
||||
expression1;
|
||||
while (expression2) {
|
||||
statement;
|
||||
expression3;
|
||||
}
|
||||
.RE
|
||||
.fi
|
||||
.IP "\fBbreak\fR"
|
||||
This statement causes a forced exit of the most recent enclosing while
|
||||
statement or for statement.
|
||||
.IP "\fBcontinue\fR"
|
||||
The continue statement (an extension) causes the most recent enclosing
|
||||
for statement to start the next iteration.
|
||||
.IP "\fBhalt\fR"
|
||||
The halt statement (an extension) is an executed statement that causes
|
||||
the \fBbc\fR processor to quit only when it is executed. For example,
|
||||
"if (0 == 1) halt" will not cause \fBbc\fR to terminate because the halt is
|
||||
not executed.
|
||||
.IP "\fBreturn\fR"
|
||||
Return the value 0 from a function. (See the section on functions.)
|
||||
.IP "\fBreturn\fR ( expression )"
|
||||
Return the value of the expression from a function. (See the section on
|
||||
functions.) As an extension, the parenthesis are not required.
|
||||
.SS PSEUDO STATEMENTS
|
||||
These statements are not statements in the traditional sense. They are
|
||||
not executed statements. Their function is performed at "compile" time.
|
||||
.IP "\fBlimits\fR"
|
||||
Print the local limits enforced by the local version of \fBbc\fR. This
|
||||
is an extension.
|
||||
.IP "\fBquit\fR"
|
||||
When the quit statement is read, the \fBbc\fR processor
|
||||
is terminated, regardless of where the quit statement is found. For
|
||||
example, "if (0 == 1) quit" will cause \fBbc\fR to terminate.
|
||||
.IP "\fBwarranty\fR"
|
||||
Print a longer warranty notice. This is an extension.
|
||||
.SS FUNCTIONS
|
||||
Functions provide a method of defining a computation that can be executed
|
||||
later. Functions in
|
||||
.B bc
|
||||
always compute a value and return it to the caller. Function definitions
|
||||
are "dynamic" in the sense that a function is undefined until a definition
|
||||
is encountered in the input. That definition is then used until another
|
||||
definition function for the same name is encountered. The new definition
|
||||
then replaces the older definition. A function is defined as follows:
|
||||
.nf
|
||||
.RS
|
||||
\fBdefine \fIname \fB( \fIparameters \fB) { \fInewline
|
||||
\fI auto_list statement_list \fB}\fR
|
||||
.RE
|
||||
.fi
|
||||
A function call is just an expression of the form
|
||||
"\fIname\fB(\fIparameters\fB)\fR".
|
||||
.PP
|
||||
Parameters are numbers or arrays (an extension). In the function definition,
|
||||
zero or more parameters are defined by listing their names separated by
|
||||
commas. All parameters are call by value parameters.
|
||||
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 value to the function. Since function definitions are dynamic,
|
||||
parameter numbers and types are checked when a function is called. Any
|
||||
mismatch in number or types of parameters will cause a runtime error.
|
||||
A runtime error will also occur for the call to an undefined function.
|
||||
.PP
|
||||
The \fIauto_list\fR is an optional list of variables that are for
|
||||
"local" use. The syntax of the auto list (if present) is "\fBauto
|
||||
\fIname\fR, ... ;". (The semicolon is optional.) Each \fIname\fR is
|
||||
the name of an auto variable. Arrays may be specified by using the
|
||||
same notation as used in parameters. These variables have their
|
||||
values pushed onto a stack at the start of the function. The
|
||||
variables are then initialized to zero and used throughout the
|
||||
execution of the function. At function exit, these variables are
|
||||
popped so that the original value (at the time of the function call)
|
||||
of these variables are restored. The parameters are really auto
|
||||
variables that are initialized to a value provided in the function
|
||||
call. Auto variables are different than traditional local variables
|
||||
because if function A calls function B, B may access function
|
||||
A's auto variables by just using the same name, unless function B has
|
||||
called them auto variables. Due to the fact that auto variables and
|
||||
parameters are pushed onto a stack, \fBbc\fR supports recursive functions.
|
||||
.PP
|
||||
The function body is a list of \fBbc\fR statements. Again, statements
|
||||
are separated by semicolons or newlines. Return statements cause the
|
||||
termination of a function and the return of a value. There are two
|
||||
versions of the return statement. The first form, "\fBreturn\fR", returns
|
||||
the value 0 to the calling expression. The second form,
|
||||
"\fBreturn ( \fIexpression \fB)\fR", computes the value of the expression
|
||||
and returns that value to the calling expression. There is an implied
|
||||
"\fBreturn (0)\fR" at the end of every function. This allows a function
|
||||
to terminate and return 0 without an explicit return statement.
|
||||
.PP
|
||||
Functions also change the usage of the variable \fBibase\fR. All
|
||||
constants in the function body will be converted using the value of
|
||||
\fBibase\fR at the time of the function call. Changes of \fBibase\fR
|
||||
will be ignored during the execution of the function except for the
|
||||
standard function \fBread\fR, which will always use the current value
|
||||
of \fBibase\fR for conversion of numbers.
|
||||
.PP
|
||||
Several extensions have been added to functions. First, the format of
|
||||
the definition has been slightly relaxed. The standard requires the
|
||||
opening brace be on the same line as the \fBdefine\fR keyword and all
|
||||
other parts must be on following lines. This version of \fBbc\fR will
|
||||
allow any number of newlines before and after the opening brace of the
|
||||
function. For example, the following definitions are legal.
|
||||
.nf
|
||||
.RS
|
||||
\f(CW
|
||||
define d (n) { return (2*n); }
|
||||
define d (n)
|
||||
{ return (2*n); }
|
||||
\fR
|
||||
.RE
|
||||
.fi
|
||||
.PP
|
||||
Functions may be defined as \fBvoid\fR. A void
|
||||
funtion returns no value and thus may not be used in any place that needs
|
||||
a value. A void function does not produce any output when called by itself
|
||||
on an input line. The key word \fBvoid\fR is placed between the key word
|
||||
\fBdefine\fR and the function name. For example, consider the following
|
||||
session.
|
||||
.nf
|
||||
.RS
|
||||
\f(CW
|
||||
define py (y) { print "--->", y, "<---", "\en"; }
|
||||
define void px (x) { print "--->", x, "<---", "\en"; }
|
||||
py(1)
|
||||
--->1<---
|
||||
0
|
||||
px(1)
|
||||
--->1<---
|
||||
\fR
|
||||
.RE
|
||||
.fi
|
||||
Since \fBpy\fR is not a void function, the call of \fBpy(1)\fR prints
|
||||
the desired output and then prints a second line that is the value of
|
||||
the function. Since the value of a function that is not given an
|
||||
explicit return statement is zero, the zero is printed. For \fBpx(1)\fR,
|
||||
no zero is printed because the function is a void function.
|
||||
.PP
|
||||
Also, call by variable for arrays was added. To declare
|
||||
a call by variable array, the declaration of the array parameter in the
|
||||
function definition looks like "\fI*name\fB[]\fR". The call to the
|
||||
function remains the same as call by value arrays.
|
||||
.SS MATH LIBRARY
|
||||
If \fBbc\fR is invoked with the \fB-l\fR option, a math library is preloaded
|
||||
and the default scale is set to 20. The math functions will calculate their
|
||||
results to the scale set at the time of their call.
|
||||
The math library defines the following functions:
|
||||
.IP "s (\fIx\fR)"
|
||||
The sine of x, x is in radians.
|
||||
.IP "c (\fIx\fR)"
|
||||
The cosine of x, x is in radians.
|
||||
.IP "a (\fIx\fR)"
|
||||
The arctangent of x, arctangent returns radians.
|
||||
.IP "l (\fIx\fR)"
|
||||
The natural logarithm of x.
|
||||
.IP "e (\fIx\fR)"
|
||||
The exponential function of raising e to the value x.
|
||||
.IP "j (\fIn,x\fR)"
|
||||
The Bessel function of integer order n of x.
|
||||
.SS EXAMPLES
|
||||
In /bin/sh, the following will assign the value of "pi" to the shell
|
||||
variable \fBpi\fR.
|
||||
.RS
|
||||
\f(CW
|
||||
pi=$(echo "scale=10; 4*a(1)" | bc -l)
|
||||
\fR
|
||||
.RE
|
||||
.PP
|
||||
The following is the definition of the exponential function used in the
|
||||
math library. This function is written in POSIX \fBbc\fR.
|
||||
.nf
|
||||
.RS
|
||||
\f(CW
|
||||
scale = 20
|
||||
|
||||
/* Uses the fact that e^x = (e^(x/2))^2
|
||||
When x is small enough, we use the series:
|
||||
e^x = 1 + x + x^2/2! + x^3/3! + ...
|
||||
*/
|
||||
|
||||
define e(x) {
|
||||
auto a, d, e, f, i, m, v, z
|
||||
|
||||
/* Check the sign of x. */
|
||||
if (x<0) {
|
||||
m = 1
|
||||
x = -x
|
||||
}
|
||||
|
||||
/* Precondition x. */
|
||||
z = scale;
|
||||
scale = 4 + z + .44*x;
|
||||
while (x > 1) {
|
||||
f += 1;
|
||||
x /= 2;
|
||||
}
|
||||
|
||||
/* Initialize the variables. */
|
||||
v = 1+x
|
||||
a = x
|
||||
d = 1
|
||||
|
||||
for (i=2; 1; i++) {
|
||||
e = (a *= x) / (d *= i)
|
||||
if (e == 0) {
|
||||
if (f>0) while (f--) v = v*v;
|
||||
scale = z
|
||||
if (m) return (1/v);
|
||||
return (v/1);
|
||||
}
|
||||
v += e
|
||||
}
|
||||
}
|
||||
\fR
|
||||
.RE
|
||||
.fi
|
||||
.PP
|
||||
The following is code that uses the extended features of \fBbc\fR to
|
||||
implement a simple program for calculating checkbook balances. This
|
||||
program is best kept in a file so that it can be used many times
|
||||
without having to retype it at every use.
|
||||
.nf
|
||||
.RS
|
||||
\f(CW
|
||||
scale=2
|
||||
print "\enCheck book program!\en"
|
||||
print " Remember, deposits are negative transactions.\en"
|
||||
print " Exit by a 0 transaction.\en\en"
|
||||
|
||||
print "Initial balance? "; bal = read()
|
||||
bal /= 1
|
||||
print "\en"
|
||||
while (1) {
|
||||
"current balance = "; bal
|
||||
"transaction? "; trans = read()
|
||||
if (trans == 0) break;
|
||||
bal -= trans
|
||||
bal /= 1
|
||||
}
|
||||
quit
|
||||
\fR
|
||||
.RE
|
||||
.fi
|
||||
.PP
|
||||
The following is the definition of the recursive factorial function.
|
||||
.nf
|
||||
.RS
|
||||
\f(CW
|
||||
define f (x) {
|
||||
if (x <= 1) return (1);
|
||||
return (f(x-1) * x);
|
||||
}
|
||||
\fR
|
||||
.RE
|
||||
.fi
|
||||
.SS READLINE AND LIBEDIT OPTIONS
|
||||
GNU \fBbc\fR can be compiled (via a configure option) to use the GNU
|
||||
\fBreadline\fR input editor library or the BSD \fBlibedit\fR library.
|
||||
This allows the user to do editing of lines before sending them
|
||||
to \fBbc\fR. It also allows for a history of previous lines typed.
|
||||
When this option is selected, \fBbc\fR has one more special variable.
|
||||
This special variable, \fBhistory\fR is the number of lines of history
|
||||
retained. For \fBreadline\fR, a value of -1 means that an unlimited
|
||||
number of history lines are retained. Setting the value of
|
||||
\fBhistory\fR to a positive number restricts the number of history
|
||||
lines to the number given. The value of 0 disables the history
|
||||
feature. The default value is 100. For more information, read the
|
||||
user manuals for the GNU \fBreadline\fR, \fBhistory\fR and BSD \fBlibedit\fR
|
||||
libraries. One can not enable both \fBreadline\fR and \fBlibedit\fR
|
||||
at the same time.
|
||||
.SS DIFFERENCES
|
||||
This version of
|
||||
.B bc
|
||||
was implemented from the POSIX P1003.2/D11 draft and contains
|
||||
several differences and extensions relative to the draft and
|
||||
traditional implementations.
|
||||
It is not implemented in the traditional way using
|
||||
.I dc(1).
|
||||
This version is a single process which parses and runs a byte code
|
||||
translation of the program. There is an "undocumented" option (-c)
|
||||
that causes the program to output the byte code to
|
||||
the standard output instead of running it. It was mainly used for
|
||||
debugging the parser and preparing the math library.
|
||||
.PP
|
||||
A major source of differences is
|
||||
extensions, where a feature is extended to add more functionality and
|
||||
additions, where new features are added.
|
||||
The following is the list of differences and extensions.
|
||||
.IP "LANG environment"
|
||||
This version does not conform to the POSIX standard in the processing
|
||||
of the LANG environment variable and all environment variables starting
|
||||
with LC_.
|
||||
.IP "names"
|
||||
Traditional and POSIX
|
||||
.B bc
|
||||
have single letter names for functions, variables and arrays. They have
|
||||
been extended to be multi-character names that start with a letter and
|
||||
may contain letters, numbers and the underscore character.
|
||||
.IP "Strings"
|
||||
Strings are not allowed to contain NUL characters. POSIX says all characters
|
||||
must be included in strings.
|
||||
.IP "last"
|
||||
POSIX \fBbc\fR does not have a \fBlast\fR variable. Some implementations
|
||||
of \fBbc\fR use the period (.) in a similar way.
|
||||
.IP "comparisons"
|
||||
POSIX \fBbc\fR allows comparisons only in the if statement, the while
|
||||
statement, and the second expression of the for statement. Also, only
|
||||
one relational operation is allowed in each of those statements.
|
||||
.IP "if statement, else clause"
|
||||
POSIX \fBbc\fR does not have an else clause.
|
||||
.IP "for statement"
|
||||
POSIX \fBbc\fR requires all expressions to be present in the for statement.
|
||||
.IP "&&, ||, !"
|
||||
POSIX \fBbc\fR does not have the logical operators.
|
||||
.IP "read function"
|
||||
POSIX \fBbc\fR does not have a read function.
|
||||
.IP "print statement"
|
||||
POSIX \fBbc\fR does not have a print statement .
|
||||
.IP "continue statement"
|
||||
POSIX \fBbc\fR does not have a continue statement.
|
||||
.IP "return statement"
|
||||
POSIX \fBbc\fR requires parentheses around the return expression.
|
||||
.IP "array parameters"
|
||||
POSIX \fBbc\fR does not (currently) support array parameters in full.
|
||||
The POSIX grammar allows for arrays in function definitions, but does
|
||||
not provide a method to specify an array as an actual parameter. (This
|
||||
is most likely an oversight in the grammar.) Traditional implementations
|
||||
of \fBbc\fR have only call by value array parameters.
|
||||
.IP "function format"
|
||||
POSIX \fBbc\fR requires the opening brace on the same line as the
|
||||
\fBdefine\fR key word and the \fBauto\fR statement on the next line.
|
||||
.IP "=+, =-, =*, =/, =%, =^"
|
||||
POSIX \fBbc\fR does not require these "old style" assignment operators to
|
||||
be defined. This version may allow these "old style" assignments. Use
|
||||
the limits statement to see if the installed version supports them. If
|
||||
it does support the "old style" assignment operators, the statement
|
||||
"a =- 1" will decrement \fBa\fR by 1 instead of setting \fBa\fR to the
|
||||
value -1.
|
||||
.IP "spaces in numbers"
|
||||
Other implementations of \fBbc\fR allow spaces in numbers. For example,
|
||||
"x=1 3" would assign the value 13 to the variable x. The same statement
|
||||
would cause a syntax error in this version of \fBbc\fR.
|
||||
.IP "errors and execution"
|
||||
This implementation varies from other implementations in terms of what
|
||||
code will be executed when syntax and other errors are found in the
|
||||
program. If a syntax error is found in a function definition, error
|
||||
recovery tries to find the beginning of a statement and continue to
|
||||
parse the function. Once a syntax error is found in the function, the
|
||||
function will not be callable and becomes undefined.
|
||||
Syntax errors in the interactive execution code will invalidate the
|
||||
current execution block. The execution block is terminated by an
|
||||
end of line that appears after a complete sequence of statements.
|
||||
For example,
|
||||
.nf
|
||||
.RS
|
||||
a = 1
|
||||
b = 2
|
||||
.RE
|
||||
.fi
|
||||
has two execution blocks and
|
||||
.nf
|
||||
.RS
|
||||
{ a = 1
|
||||
b = 2 }
|
||||
.RE
|
||||
.fi
|
||||
has one execution block. Any runtime error will terminate the execution
|
||||
of the current execution block. A runtime warning will not terminate the
|
||||
current execution block.
|
||||
.IP "Interrupts"
|
||||
During an interactive session, the SIGINT signal (usually generated by
|
||||
the control-C character from the terminal) will cause execution of the
|
||||
current execution block to be interrupted. It will display a "runtime"
|
||||
error indicating which function was interrupted. After all runtime
|
||||
structures have been cleaned up, a message will be printed to notify the
|
||||
user that \fBbc\fR is ready for more input. All previously defined functions
|
||||
remain defined and the value of all non-auto variables are the value at
|
||||
the point of interruption. All auto variables and function parameters
|
||||
are removed during the
|
||||
clean up process. During a non-interactive
|
||||
session, the SIGINT signal will terminate the entire run of \fBbc\fR.
|
||||
.SS LIMITS
|
||||
The following are the limits currently in place for this
|
||||
.B bc
|
||||
processor. Some of them may have been changed by an installation.
|
||||
Use the limits statement to see the actual values.
|
||||
.IP "BC_BASE_MAX"
|
||||
The maximum output base is currently set at 999. The maximum input base
|
||||
is 16.
|
||||
.IP "BC_DIM_MAX"
|
||||
This is currently an arbitrary limit of 65535 as distributed. Your
|
||||
installation may be different.
|
||||
.IP "BC_SCALE_MAX"
|
||||
The number of digits after the decimal point is limited to INT_MAX digits.
|
||||
Also, the number of digits before the decimal point is limited to INT_MAX
|
||||
digits.
|
||||
.IP "BC_STRING_MAX"
|
||||
The limit on the number of characters in a string is INT_MAX characters.
|
||||
.IP "exponent"
|
||||
The value of the exponent in the raise operation (^) is limited to LONG_MAX.
|
||||
.IP "variable names"
|
||||
The current limit on the number of unique names is 32767 for each of
|
||||
simple variables, arrays and functions.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
The following environment variables are processed by \fBbc\fR:
|
||||
.IP "POSIXLY_CORRECT"
|
||||
This is the same as the \fB-s\fR option.
|
||||
.IP "BC_ENV_ARGS"
|
||||
This is another mechanism to get arguments to \fBbc\fR. The
|
||||
format is the same as the command line arguments. These arguments
|
||||
are processed first, so any files listed in the environment arguments
|
||||
are processed before any command line argument files. This allows
|
||||
the user to set up "standard" options and files to be processed
|
||||
at every invocation of \fBbc\fR. The files in the environment
|
||||
variables would typically contain function definitions for functions
|
||||
the user wants defined every time \fBbc\fR is run.
|
||||
.IP "BC_LINE_LENGTH"
|
||||
This should be an integer specifying the number of characters in an
|
||||
output line for numbers. This includes the backslash and newline characters
|
||||
for long numbers. As an extension, the value of zero disables the
|
||||
multi-line feature. Any other value of this variable that is less than
|
||||
3 sets the line length to 70.
|
||||
.SH DIAGNOSTICS
|
||||
If any file on the command line can not be opened, \fBbc\fR will report
|
||||
that the file is unavailable and terminate. Also, there are compile
|
||||
and run time diagnostics that should be self-explanatory.
|
||||
.SH BUGS
|
||||
Error recovery is not very good yet.
|
||||
.PP
|
||||
Email bug reports to
|
||||
.BR bug-bc@gnu.org .
|
||||
Be sure to include the word ``bc'' somewhere in the ``Subject:'' field.
|
||||
.SH AUTHOR
|
||||
.nf
|
||||
Philip A. Nelson
|
||||
philnelson@acm.org
|
||||
.fi
|
||||
.SH ACKNOWLEDGEMENTS
|
||||
The author would like to thank Steve Sommars (Steve.Sommars@att.com) for
|
||||
his extensive help in testing the implementation. Many great suggestions
|
||||
were given. This is a much better product due to his involvement.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,520 @@
|
|||
.\"
|
||||
.\" dc.1 - the *roff document processor source for the dc manual
|
||||
.\"
|
||||
.\" This file is part of GNU dc.
|
||||
.\" Copyright (C) 1994, 1997, 1998, 2000, 2001, 2005, 2006, 2008, 2013, 2016
|
||||
.\" Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" Permission is granted to copy, distribute and/or modify this document
|
||||
.\" under the terms of the GNU Free Documentation License, Version 1.2 or
|
||||
.\" any later version published by the Free Software Foundation; with no
|
||||
.\" Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
|
||||
.\" Texts.
|
||||
.\"
|
||||
.TH dc 1 "2008-05-22" "GNU Project"
|
||||
.ds dc \fIdc\fP
|
||||
.ds Dc \fIdc\fP
|
||||
.SH NAME
|
||||
dc \- an arbitrary precision calculator
|
||||
.SH SYNOPSIS
|
||||
dc [-V] [--version] [-h] [--help]
|
||||
[-e scriptexpression] [--expression=scriptexpression]
|
||||
[-f scriptfile] [--file=scriptfile]
|
||||
[file ...]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\*(Dc is a reverse-polish desk calculator which supports
|
||||
unlimited precision arithmetic.
|
||||
It also allows you to define and call macros.
|
||||
Normally \*(dc reads from the standard input;
|
||||
if any command arguments are given to it, they are filenames,
|
||||
and \*(dc reads and executes the contents of the files before reading
|
||||
from standard input.
|
||||
All normal output is to standard output;
|
||||
all error output is to standard error.
|
||||
.PP
|
||||
A reverse-polish calculator stores numbers on a stack.
|
||||
Entering a number pushes it on the stack.
|
||||
Arithmetic operations pop arguments off the stack and push the results.
|
||||
.PP
|
||||
To enter a number in
|
||||
.IR dc ,
|
||||
type the digits
|
||||
(using upper case letters
|
||||
.I A
|
||||
through
|
||||
.I F
|
||||
as "digits" when working
|
||||
with input bases greater than ten),
|
||||
with an optional decimal point.
|
||||
Exponential notation is not supported.
|
||||
To enter a negative number,
|
||||
begin the number with ``_''.
|
||||
``-'' cannot be used for this,
|
||||
as it is a binary operator for subtraction instead.
|
||||
To enter two numbers in succession,
|
||||
separate them with spaces or newlines.
|
||||
These have no meaning as commands.
|
||||
.SH OPTIONS
|
||||
\*(Dc may be invoked with the following command-line options:
|
||||
.TP
|
||||
.B -V
|
||||
.TP
|
||||
.B --version
|
||||
Print out the version of \*(dc that is being run and a copyright notice,
|
||||
then exit.
|
||||
.TP
|
||||
.B -h
|
||||
.TP
|
||||
.B --help
|
||||
Print a usage message briefly summarizing these command-line options
|
||||
and the bug-reporting address,
|
||||
then exit.
|
||||
.TP
|
||||
.B -e \fIscript\fP
|
||||
.TP
|
||||
.BI --expression= script
|
||||
Add the commands in
|
||||
.I script
|
||||
to the set of commands to be run while processing the input.
|
||||
.TP
|
||||
.B -f \fIscript-file\fP
|
||||
.TP
|
||||
.BI --file= script-file
|
||||
Add the commands contained in the file
|
||||
.I script-file
|
||||
to the set of commands to be run while processing the input.
|
||||
.PP
|
||||
If any command-line parameters remain after processing the above,
|
||||
these parameters are interpreted as the names of input files to
|
||||
be processed.
|
||||
A file name of
|
||||
.B -
|
||||
refers to the standard input stream.
|
||||
The standard input will processed if no script files or
|
||||
expressions are specified.
|
||||
.PD
|
||||
.SH
|
||||
Printing Commands
|
||||
.TP
|
||||
.B p
|
||||
Prints the value on the top of the stack,
|
||||
without altering the stack.
|
||||
A newline is printed after the value.
|
||||
.TP
|
||||
.B n
|
||||
Prints the value on the top of the stack, popping it off,
|
||||
and does not print a newline after.
|
||||
.TP
|
||||
.B P
|
||||
Pops off the value on top of the stack.
|
||||
If it it a string, it is simply printed without a trailing newline.
|
||||
Otherwise it is a number, and the integer portion of its absolute
|
||||
value is printed out as a "base (UCHAR_MAX+1)" byte stream.
|
||||
Assuming that (UCHAR_MAX+1) is 256
|
||||
(as it is on most machines with 8-bit bytes),
|
||||
the sequence \fBKSK0k1/_1Ss [ls*]Sxd0>x
|
||||
[256~Ssd0<x]dsxxsx[q]Sq[Lsd0>qaPlxx]
|
||||
dsxxsx0sqLqsxLxLK+k\fP
|
||||
could also accomplish this function.
|
||||
(Much of the complexity of the above native-dc code is due
|
||||
to the ~ computing the characters backwards,
|
||||
and the desire to ensure that all registers wind up back
|
||||
in their original states.)
|
||||
.TP
|
||||
.B f
|
||||
Prints the entire contents of the stack
|
||||
.ig
|
||||
and the contents of all of the registers,
|
||||
..
|
||||
without altering anything.
|
||||
This is a good command to use if you are lost or want
|
||||
to figure out what the effect of some command has been.
|
||||
.PD
|
||||
.SH
|
||||
Arithmetic
|
||||
.TP
|
||||
.B +
|
||||
Pops two values off the stack, adds them,
|
||||
and pushes the result.
|
||||
The precision of the result is determined only
|
||||
by the values of the arguments,
|
||||
and is enough to be exact.
|
||||
.TP
|
||||
.B -
|
||||
Pops two values,
|
||||
subtracts the first one popped from the second one popped,
|
||||
and pushes the result.
|
||||
.TP
|
||||
.B *
|
||||
Pops two values, multiplies them, and pushes the result.
|
||||
The number of fraction digits in the result depends on
|
||||
the current precision value and the number of fraction
|
||||
digits in the two arguments.
|
||||
.TP
|
||||
.B /
|
||||
Pops two values,
|
||||
divides the second one popped from the first one popped,
|
||||
and pushes the result.
|
||||
The number of fraction digits is specified by the precision value.
|
||||
.TP
|
||||
.B %
|
||||
Pops two values,
|
||||
computes the remainder of the division that the
|
||||
.B /
|
||||
command would do,
|
||||
and pushes that.
|
||||
The value computed is the same as that computed by
|
||||
the sequence \fBSd dld/ Ld*-\fP .
|
||||
.TP
|
||||
.B ~
|
||||
Pops two values,
|
||||
divides the second one popped from the first one popped.
|
||||
The quotient is pushed first, and the remainder is pushed next.
|
||||
The number of fraction digits used in the division
|
||||
is specified by the precision value.
|
||||
(The sequence \fBSdSn lnld/ LnLd%\fP could also accomplish
|
||||
this function, with slightly different error checking.)
|
||||
.TP
|
||||
.B ^
|
||||
Pops two values and exponentiates,
|
||||
using the first value popped as the exponent
|
||||
and the second popped as the base.
|
||||
The fraction part of the exponent is ignored.
|
||||
The precision value specifies the number of fraction
|
||||
digits in the result.
|
||||
.TP
|
||||
.B |
|
||||
Pops three values and computes a modular exponentiation.
|
||||
The first value popped is used as the reduction modulus;
|
||||
this value must be a non-zero number,
|
||||
and should be an integer.
|
||||
The second popped is used as the exponent;
|
||||
this value must be a non-negative number,
|
||||
and any fractional part of this exponent will be ignored.
|
||||
The third value popped is the base which gets exponentiated,
|
||||
which should be an integer.
|
||||
For small integers this is like the sequence \fBSm^Lm%\fP,
|
||||
but, unlike \fB^\fP, this command will work with arbitrarily large exponents.
|
||||
.TP
|
||||
.B v
|
||||
Pops one value,
|
||||
computes its square root,
|
||||
and pushes that.
|
||||
The maximum of the precision value and the precision of the argument
|
||||
is used to determine the number of fraction digits in the result.
|
||||
.PP
|
||||
Most arithmetic operations are affected by the ``precision value'',
|
||||
which you can set with the
|
||||
.B k
|
||||
command.
|
||||
The default precision value is zero,
|
||||
which means that all arithmetic except for
|
||||
addition and subtraction produces integer results.
|
||||
.SH
|
||||
Stack Control
|
||||
.TP
|
||||
.B c
|
||||
Clears the stack, rendering it empty.
|
||||
.TP
|
||||
.B d
|
||||
Duplicates the value on the top of the stack,
|
||||
pushing another copy of it.
|
||||
Thus, ``4d*p'' computes 4 squared and prints it.
|
||||
.TP
|
||||
.B r
|
||||
Reverses the order of (swaps) the top two values on the stack.
|
||||
(This can also be accomplished with the sequence \fBSaSbLaLb\fP.)
|
||||
.TP
|
||||
.B R
|
||||
Pops the top-of-stack as an integer
|
||||
.IR n .
|
||||
Cyclically rotates the top
|
||||
.I n
|
||||
items on the updated stack.
|
||||
If
|
||||
.I n
|
||||
is positive, then the rotation direction will make the topmost
|
||||
element the second-from top;
|
||||
if
|
||||
.I n
|
||||
is negative, then the rotation will make the topmost element the
|
||||
.IR n -th
|
||||
element from the top.
|
||||
If the stack depth is less than
|
||||
.IR n ,
|
||||
then the entire stack is rotated (in the appropriate direction),
|
||||
without any error being reported.
|
||||
.SH
|
||||
Registers
|
||||
.PP
|
||||
\*(Dc provides at least 256 memory registers,
|
||||
each named by a single character.
|
||||
You can store a number or a string in a register and retrieve it later.
|
||||
.TP
|
||||
.BI s r
|
||||
Pop the value off the top of the stack and store
|
||||
it into register
|
||||
.IR r .
|
||||
.TP
|
||||
.BI l r
|
||||
Copy the value in register
|
||||
.I r
|
||||
and push it onto the stack.
|
||||
The value 0 is retrieved if the register is uninitialized.
|
||||
This does not alter the contents of
|
||||
.IR r .
|
||||
.PP
|
||||
Each register also contains its own stack.
|
||||
The current register value is the top of the register's stack.
|
||||
.TP
|
||||
.BI S r
|
||||
Pop the value off the top of the (main) stack and
|
||||
push it onto the stack of register
|
||||
.IR r .
|
||||
The previous value of the register becomes inaccessible.
|
||||
.TP
|
||||
.BI L r
|
||||
Pop the value off the top of register
|
||||
.IR r 's
|
||||
stack and push it onto the main stack.
|
||||
The previous value
|
||||
in register
|
||||
.IR r 's
|
||||
stack, if any,
|
||||
is now accessible via the
|
||||
.BI l r
|
||||
command.
|
||||
.ig
|
||||
.PP
|
||||
The
|
||||
.B f
|
||||
command prints a list of all registers that have contents stored in them,
|
||||
together with their contents.
|
||||
Only the current contents of each register
|
||||
(the top of its stack)
|
||||
is printed.
|
||||
..
|
||||
.SH
|
||||
Parameters
|
||||
.PP
|
||||
\*(Dc has three parameters that control its operation:
|
||||
the precision, the input radix, and the output radix.
|
||||
The precision specifies the number
|
||||
of fraction digits to keep in the result of most arithmetic operations.
|
||||
The input radix controls the interpretation of numbers typed in;
|
||||
all numbers typed in use this radix.
|
||||
The output radix is used for printing numbers.
|
||||
.PP
|
||||
The input and output radices are separate parameters;
|
||||
you can make them unequal,
|
||||
which can be useful or confusing.
|
||||
The input radix must be between 2 and 16 inclusive.
|
||||
The output radix must be at least 2.
|
||||
The precision must be zero or greater.
|
||||
The precision is always measured in decimal digits,
|
||||
regardless of the current input or output radix.
|
||||
.TP
|
||||
.B i
|
||||
Pops the value off the top of the stack
|
||||
and uses it to set the input radix.
|
||||
.TP
|
||||
.B o
|
||||
Pops the value off the top of the stack
|
||||
and uses it to set the output radix.
|
||||
.TP
|
||||
.B k
|
||||
Pops the value off the top of the stack
|
||||
and uses it to set the precision.
|
||||
.TP
|
||||
.B I
|
||||
Pushes the current input radix on the stack.
|
||||
.TP
|
||||
.B O
|
||||
Pushes the current output radix on the stack.
|
||||
.TP
|
||||
.B K
|
||||
Pushes the current precision on the stack.
|
||||
.SH
|
||||
Strings
|
||||
.PP
|
||||
\*(Dc has a limited ability to operate on strings
|
||||
as well as on numbers;
|
||||
the only things you can do with strings are
|
||||
print them and execute them as macros
|
||||
(which means that the contents of the string are processed as
|
||||
\*(dc commands).
|
||||
All registers and the stack can hold strings,
|
||||
and \*(dc always knows whether any given object is a string or a number.
|
||||
Some commands such as arithmetic operations demand numbers
|
||||
as arguments and print errors if given strings.
|
||||
Other commands can accept either a number or a string;
|
||||
for example, the
|
||||
.B p
|
||||
command can accept either and prints the object
|
||||
according to its type.
|
||||
.TP
|
||||
.BI [ characters ]
|
||||
Makes a string containing
|
||||
.I characters
|
||||
(contained between balanced
|
||||
.B [
|
||||
and
|
||||
.B ]
|
||||
characters),
|
||||
and pushes it on the stack.
|
||||
For example,
|
||||
.B [foo]P
|
||||
prints the characters
|
||||
.B foo
|
||||
(with no newline).
|
||||
.TP
|
||||
.B a
|
||||
The top-of-stack is popped.
|
||||
If it was a number, then the low-order byte of this number
|
||||
is converted into a string and pushed onto the stack.
|
||||
Otherwise the top-of-stack was a string,
|
||||
and the first character of that string is pushed back.
|
||||
.TP
|
||||
.B x
|
||||
Pops a value off the stack and executes it as a macro.
|
||||
Normally it should be a string;
|
||||
if it is a number,
|
||||
it is simply pushed back onto the stack.
|
||||
For example,
|
||||
.B [1p]x
|
||||
executes the macro
|
||||
.B 1p
|
||||
which pushes
|
||||
.B 1
|
||||
on the stack and prints
|
||||
.B 1
|
||||
on a separate line.
|
||||
.PP
|
||||
Macros are most often stored in registers;
|
||||
.B [1p]sa
|
||||
stores a macro to print
|
||||
.B 1
|
||||
into register
|
||||
.BR a ,
|
||||
and
|
||||
.B lax
|
||||
invokes this macro.
|
||||
.TP
|
||||
.BI > r
|
||||
Pops two values off the stack and compares them
|
||||
assuming they are numbers,
|
||||
executing the contents of register
|
||||
.I r
|
||||
as a macro if the original top-of-stack
|
||||
is greater.
|
||||
Thus,
|
||||
.B 1 2>a
|
||||
will invoke register
|
||||
.BR a 's
|
||||
contents and
|
||||
.B 2 1>a
|
||||
will not.
|
||||
.TP
|
||||
.BI !> r
|
||||
Similar but invokes the macro if the original top-of-stack is
|
||||
not greater than (less than or equal to) what was the second-to-top.
|
||||
.TP
|
||||
.BI < r
|
||||
Similar but invokes the macro if the original top-of-stack is less.
|
||||
.TP
|
||||
.BI !< r
|
||||
Similar but invokes the macro if the original top-of-stack is
|
||||
not less than (greater than or equal to) what was the second-to-top.
|
||||
.TP
|
||||
.BI = r
|
||||
Similar but invokes the macro if the two numbers popped are equal.
|
||||
.TP
|
||||
.BI != r
|
||||
Similar but invokes the macro if the two numbers popped are not equal.
|
||||
.ig
|
||||
This can also be validly used to compare two strings for equality.
|
||||
..
|
||||
.TP
|
||||
.B ?
|
||||
Reads a line from the terminal and executes it.
|
||||
This command allows a macro to request input from the user.
|
||||
.TP
|
||||
.B q
|
||||
exits from a macro and also from the macro which invoked it.
|
||||
If called from the top level,
|
||||
or from a macro which was called directly from the top level,
|
||||
the
|
||||
.B q
|
||||
command will cause \*(dc to exit.
|
||||
.TP
|
||||
.B Q
|
||||
Pops a value off the stack and uses it as a count
|
||||
of levels of macro execution to be exited.
|
||||
Thus,
|
||||
.B 3Q
|
||||
exits three levels.
|
||||
The
|
||||
.B Q
|
||||
command will never cause \*(dc to exit.
|
||||
.SH
|
||||
Status Inquiry
|
||||
.TP
|
||||
.B Z
|
||||
Pops a value off the stack,
|
||||
calculates the number of decimal digits it has
|
||||
(or number of characters, if it is a string)
|
||||
and pushes that number.
|
||||
The digit count for a number does
|
||||
.I not
|
||||
include any leading zeros,
|
||||
even if those appear to the right of the radix point.
|
||||
.TP
|
||||
.B X
|
||||
Pops a value off the stack,
|
||||
calculates the number of fraction digits it has,
|
||||
and pushes that number.
|
||||
For a string,
|
||||
the value pushed is
|
||||
.\" -1.
|
||||
0.
|
||||
.TP
|
||||
.B z
|
||||
Pushes the current stack depth:
|
||||
the number of objects on the stack before the execution of the
|
||||
.B z
|
||||
command.
|
||||
.SH
|
||||
Miscellaneous
|
||||
.TP
|
||||
.B !
|
||||
Will run the rest of the line as a system command.
|
||||
Note that parsing of the !<, !=, and !> commands take precedence,
|
||||
so if you want to run a command starting with <, =, or > you will
|
||||
need to add a space after the !.
|
||||
.TP
|
||||
.B #
|
||||
Will interpret the rest of the line as a comment.
|
||||
.TP
|
||||
.BI : r
|
||||
Will pop the top two values off of the stack.
|
||||
The old second-to-top value will be stored in the array
|
||||
.IR r ,
|
||||
indexed by the old top-of-stack value.
|
||||
.TP
|
||||
.BI ; r
|
||||
Pops the top-of-stack and uses it as an index into
|
||||
the array
|
||||
.IR r .
|
||||
The selected value is then pushed onto the stack.
|
||||
.P
|
||||
Note that each stacked instance of a register has its own
|
||||
array associated with it.
|
||||
Thus \fB1 0:a 0Sa 2 0:a La 0;ap\fP will print 1,
|
||||
because the 2 was stored in an instance of 0:a that
|
||||
was later popped.
|
||||
.SH
|
||||
BUGS
|
||||
.PP
|
||||
Email bug reports to
|
||||
.BR bug-dc@gnu.org .
|
|
@ -0,0 +1,498 @@
|
|||
This is ../../doc/dc.info, produced by makeinfo version 4.8 from
|
||||
../../doc/dc.texi.
|
||||
|
||||
START-INFO-DIR-ENTRY
|
||||
* dc: (dc). Arbitrary precision RPN "Desktop Calculator".
|
||||
END-INFO-DIR-ENTRY
|
||||
|
||||
This manual documents version 1.4.1 of GNU `dc', an arbitrary
|
||||
precision calculator.
|
||||
|
||||
Copyright (C) 1984, 1994, 1997, 1998, 2000, 2005, 2006, 2008, 2013,
|
||||
2016 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
Version 1.2 or any later version published by the Free Software
|
||||
Foundation; with no Invariant Sections, with no Front-Cover Texts,
|
||||
and with no Back-Cover Texts. A copy of the license can be found
|
||||
at `http://www.gnu.org/licenses/fdl.html' .
|
||||
|
||||
|
||||
File: dc.info, Node: Top, Next: Introduction, Up: (dir)
|
||||
|
||||
GNU dc
|
||||
******
|
||||
|
||||
This manual documents version 1.4.1 of GNU `dc', an arbitrary precision
|
||||
calculator.
|
||||
|
||||
Copyright (C) 1984, 1994, 1997, 1998, 2000, 2005, 2006, 2008, 2013,
|
||||
2016 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU Free Documentation License,
|
||||
Version 1.2 or any later version published by the Free Software
|
||||
Foundation; with no Invariant Sections, with no Front-Cover Texts,
|
||||
and with no Back-Cover Texts. A copy of the license can be found
|
||||
at `http://www.gnu.org/licenses/fdl.html' .
|
||||
|
||||
* Menu:
|
||||
|
||||
* Introduction:: Introduction
|
||||
* Invocation:: Invocation
|
||||
* Printing Commands:: Printing Commands
|
||||
* Arithmetic:: Arithmetic
|
||||
* Stack Control:: Stack Control
|
||||
* Registers:: Registers
|
||||
* Parameters:: Parameters
|
||||
* Strings:: Strings
|
||||
* Status Inquiry:: Status Inquiry
|
||||
* Miscellaneous:: Other commands
|
||||
* Reporting bugs:: Reporting bugs
|
||||
|
||||
|
||||
File: dc.info, Node: Introduction, Next: Invocation, Prev: Top, Up: Top
|
||||
|
||||
1 Introduction
|
||||
**************
|
||||
|
||||
`dc' is a reverse-polish desk calculator which supports unlimited
|
||||
precision arithmetic. It also allows you to define and call macros.
|
||||
Normally `dc' reads from the standard input; if any command arguments
|
||||
are given to it, they are filenames, and `dc' reads and executes the
|
||||
contents of the files instead of reading from standard input. All
|
||||
normal output is to standard output; all error messages are written to
|
||||
standard error.
|
||||
|
||||
To exit, use `q'. `C-c' (or whatever other keystroke your system
|
||||
uses to generate a `SIGINT') does not exit; it is used to abort macros
|
||||
that are looping, etc.
|
||||
|
||||
A reverse-polish calculator stores numbers on a stack. Entering a
|
||||
number pushes it on the stack. Arithmetic operations pop arguments off
|
||||
the stack and push the results.
|
||||
|
||||
To enter a number in `dc', type the digits (using upper case letters
|
||||
`A' through `F' as "digits" when working with input bases greater than
|
||||
ten), with an optional decimal point. Exponential notation is not
|
||||
supported. To enter a negative number, begin the number with `_'. `-'
|
||||
cannot be used for this, as it is a binary operator for subtraction
|
||||
instead. To enter two numbers in succession, separate them with spaces
|
||||
or newlines; these have no meaning as commands.
|
||||
|
||||
|
||||
File: dc.info, Node: Invocation, Next: Printing Commands, Prev: Introduction, Up: Top
|
||||
|
||||
2 Invocation
|
||||
************
|
||||
|
||||
`dc' may be invoked with the following command-line options:
|
||||
`-e EXPR'
|
||||
|
||||
`--expression=EXPR'
|
||||
Evaluate EXPR as `dc' commands.
|
||||
|
||||
`-f FILE'
|
||||
|
||||
`--file=FILE'
|
||||
Read and evaluate `dc' commands from FILE.
|
||||
|
||||
`-h'
|
||||
|
||||
`--help'
|
||||
Print a usage message summarizing the command-line options, then
|
||||
exit.
|
||||
|
||||
`-V'
|
||||
|
||||
`--version'
|
||||
Print the version information for this program, then exit.
|
||||
|
||||
If any command-line parameters remain after processing the options,
|
||||
these parameters are interpreted as additional FILEs whose contents are
|
||||
read and evaluated. A file name of `-' refers to the standard input
|
||||
stream. If no `-e' option was specified, and no files were specified,
|
||||
then the standard input will be read for commands to evaluate.
|
||||
|
||||
|
||||
File: dc.info, Node: Printing Commands, Next: Arithmetic, Prev: Invocation, Up: Top
|
||||
|
||||
3 Printing Commands
|
||||
*******************
|
||||
|
||||
`p'
|
||||
Prints the value on the top of the stack, without altering the
|
||||
stack. A newline is printed after the value.
|
||||
|
||||
`n'
|
||||
Prints the value on the top of the stack, popping it off, and does
|
||||
not print a newline after. (This command is a GNU extension.)
|
||||
|
||||
`P'
|
||||
Pops off the value on top of the stack. If it it a string, it is
|
||||
simply printed without a trailing newline. Otherwise it is a
|
||||
number, and the integer portion of its absolute value is printed
|
||||
out as a "base (UCHAR_MAX+1)" byte stream. Assuming that
|
||||
(UCHAR_MAX+1) is 256 (as it is on most machines with 8-bit bytes),
|
||||
the sequence `KSK0k1/ _1Ss[ls*]Sxd0>x [256~Ssd0<x]dsxx
|
||||
sx[q]Sq[Lsd0>qaPlxx]dsxx sx0sqLqsxLxLK+k' could also accomplish
|
||||
this function. (Much of the complexity of the above native-dc
|
||||
code is due to the ~ computing the characters backwards, and the
|
||||
desire to ensure that all registers wind up back in their original
|
||||
states.) (Details of the behavior with a number are a GNU
|
||||
extension. Traditional `dc' happened to "support" similar
|
||||
functionality for a limited range of inputs as an accidental
|
||||
side-effect of its internal representation of numbers.)
|
||||
|
||||
`f'
|
||||
Prints the entire contents of the stack without altering anything.
|
||||
This is a good command to use if you are lost or want to figure
|
||||
out what the effect of some command has been.
|
||||
|
||||
All numeric output is split to fit within 70 columns, by default.
|
||||
When a number is broken up in this way, the split is indicated by a "\"
|
||||
at the end of the to-be-continued output lines. The column width at
|
||||
which output is split can be overridden by setting the DC_LINE_LENGTH
|
||||
environment variable to the desired width. A DC_LINE_LENGTH of 0
|
||||
(zero) disables the line-split feature altogether. Invalid values of
|
||||
DC_LINE_LENGTH are silently ignored. (The DC_LINE_LENGTH variable is a
|
||||
GNU extension.)
|
||||
|
||||
|
||||
File: dc.info, Node: Arithmetic, Next: Stack Control, Prev: Printing Commands, Up: Top
|
||||
|
||||
4 Arithmetic
|
||||
************
|
||||
|
||||
`+'
|
||||
Pops two values off the stack, adds them, and pushes the result.
|
||||
The precision of the result is determined only by the values of
|
||||
the arguments, and is enough to be exact.
|
||||
|
||||
`-'
|
||||
Pops two values, subtracts the first one popped from the second
|
||||
one popped, and pushes the result.
|
||||
|
||||
`*'
|
||||
Pops two values, multiplies them, and pushes the result. The
|
||||
number of fraction digits in the result is the largest of the
|
||||
precision value, the number of fraction digits in the multiplier,
|
||||
or the number of fraction digits in the multiplicand; but in no
|
||||
event exceeding the number of digits required for an exact result.
|
||||
|
||||
`/'
|
||||
Pops two values, divides the second one popped from the first one
|
||||
popped, and pushes the result. The number of fraction digits is
|
||||
specified by the precision value.
|
||||
|
||||
`%'
|
||||
Pops two values, computes the remainder of the division that the
|
||||
`/' command would do, and pushes that. The value computed is the
|
||||
same as that computed by the sequence `Sd dld/ Ld*-' .
|
||||
|
||||
`~'
|
||||
Pops two values, divides the second one popped from the first one
|
||||
popped. The quotient is pushed first, and the remainder is pushed
|
||||
next. The number of fraction digits used in the division is
|
||||
specified by the precision value. (The sequence `SdSn lnld/
|
||||
LnLd%' could also accomplish this function, with slightly
|
||||
different error checking.) (This command is a GNU extension.)
|
||||
|
||||
`^'
|
||||
Pops two values and exponentiates, using the first value popped as
|
||||
the exponent and the second popped as the base. The fraction part
|
||||
of the exponent is ignored. The precision value specifies the
|
||||
number of fraction digits in the result.
|
||||
|
||||
`|'
|
||||
Pops three values and computes a modular exponentiation. The
|
||||
first value popped is used as the reduction modulus; this value
|
||||
must be a non-zero number, and the result may not be accurate if
|
||||
the modulus is not an integer. The second popped is used as the
|
||||
exponent; this value must be a non-negative number, and any
|
||||
fractional part of this exponent will be ignored. The third value
|
||||
popped is the base which gets exponentiated, which should be an
|
||||
integer. For small integers this is like the sequence `Sm^Lm%',
|
||||
but, unlike `^', this command will work with arbitrarily large
|
||||
exponents. (This command is a GNU extension.)
|
||||
|
||||
`v'
|
||||
Pops one value, computes its square root, and pushes that. The
|
||||
maximum of the precision value and the precision of the argument
|
||||
is used to determine the number of fraction digits in the result.
|
||||
|
||||
Most arithmetic operations are affected by the _precision value_,
|
||||
which you can set with the `k' command. The default precision value is
|
||||
zero, which means that all arithmetic except for addition and
|
||||
subtraction produces integer results.
|
||||
|
||||
|
||||
File: dc.info, Node: Stack Control, Next: Registers, Prev: Arithmetic, Up: Top
|
||||
|
||||
5 Stack Control
|
||||
***************
|
||||
|
||||
`c'
|
||||
Clears the stack, rendering it empty.
|
||||
|
||||
`d'
|
||||
Duplicates the value on the top of the stack, pushing another copy
|
||||
of it. Thus, `4d*p' computes 4 squared and prints it.
|
||||
|
||||
`r'
|
||||
Reverses the order of (swaps) the top two values on the stack.
|
||||
(This can also be accomplished with the sequence `SaSbLaLb'.)
|
||||
(This command is a GNU extension.)
|
||||
|
||||
`R'
|
||||
Pops the top-of-stack as an integer N. Cyclically rotates the top
|
||||
N items on the updated stack. If N is positive, then the rotation
|
||||
direction will make the topmost element the second-from top; if N
|
||||
is negative, then the rotation will make the topmost element the
|
||||
N-th element from the top. If the stack depth is less than N then
|
||||
the entire stack is rotated (in the appropriate direction),
|
||||
without any error being reported. (This command is a GNU
|
||||
extension.)
|
||||
|
||||
|
||||
File: dc.info, Node: Registers, Next: Parameters, Prev: Stack Control, Up: Top
|
||||
|
||||
6 Registers
|
||||
***********
|
||||
|
||||
`dc' provides at least 256 memory registers(1), each named by a single
|
||||
character. You can store a number in a register and retrieve it later.
|
||||
|
||||
`sR'
|
||||
Pop the value off the top of the stack and store it into register
|
||||
R.
|
||||
|
||||
`lR'
|
||||
Copy the value in register R, and push it onto the stack. The
|
||||
value `0' is retrieved if the register is uninitialized or its
|
||||
stack has become empty. This does not alter the contents of R.
|
||||
|
||||
Each register also contains its own stack. The current register
|
||||
value is the top of the register's stack.
|
||||
|
||||
`SR'
|
||||
Pop the value off the top of the (main) stack and push it onto the
|
||||
stack of register R. The previous value of the register becomes
|
||||
inaccessible.
|
||||
|
||||
`LR'
|
||||
Pop the value off the top of register R's stack and push it onto
|
||||
the main stack. The previous value in register R's stack, if any,
|
||||
is now accessible via the `lR' command.
|
||||
|
||||
---------- Footnotes ----------
|
||||
|
||||
(1) The exact number of registers provided by `dc' depends on the
|
||||
range of an `unsigned char' in the C compiler used to create the `dc'
|
||||
executable.
|
||||
|
||||
|
||||
File: dc.info, Node: Parameters, Next: Strings, Prev: Registers, Up: Top
|
||||
|
||||
7 Parameters
|
||||
************
|
||||
|
||||
`dc' has three parameters that control its operation: the precision,
|
||||
the input radix, and the output radix. The precision specifies the
|
||||
number of fraction digits to keep in the result of most arithmetic
|
||||
operations. The input radix controls the interpretation of numbers
|
||||
typed in; _all_ numbers typed in use this radix. The output radix is
|
||||
used for printing numbers.
|
||||
|
||||
The input and output radices are separate parameters; you can make
|
||||
them unequal, which can be useful or confusing. The input radix must
|
||||
be between 2 and 16 inclusive. The output radix must be at least 2.
|
||||
The precision must be zero or greater. The precision is always
|
||||
measured in decimal digits, regardless of the current input or output
|
||||
radix.
|
||||
|
||||
`i'
|
||||
Pops the value off the top of the stack and uses it to set the
|
||||
input radix.
|
||||
|
||||
`o'
|
||||
Pops the value off the top of the stack and uses it to set the
|
||||
output radix.
|
||||
|
||||
`k'
|
||||
Pops the value off the top of the stack and uses it to set the
|
||||
precision.
|
||||
|
||||
`I'
|
||||
Pushes the current input radix on the stack.
|
||||
|
||||
`O'
|
||||
Pushes the current output radix on the stack.
|
||||
|
||||
`K'
|
||||
Pushes the current precision on the stack.
|
||||
|
||||
|
||||
|
||||
File: dc.info, Node: Strings, Next: Status Inquiry, Prev: Parameters, Up: Top
|
||||
|
||||
8 Strings
|
||||
*********
|
||||
|
||||
`dc' has a limited ability to operate on strings as well as on numbers;
|
||||
the only things you can do with strings are print them and execute them
|
||||
as macros (which means that the contents of the string are processed as
|
||||
`dc' commands). Both registers and the stack can hold strings, and
|
||||
`dc' always knows whether any given object is a string or a number.
|
||||
Some commands such as arithmetic operations demand numbers as arguments
|
||||
and print errors if given strings. Other commands can accept either a
|
||||
number or a string; for example, the `p' command can accept either and
|
||||
prints the object according to its type.
|
||||
|
||||
`[CHARACTERS]'
|
||||
Makes a string containing CHARACTERS and pushes it on the stack.
|
||||
For example, `[foo]P' prints the characters `foo' (with no
|
||||
newline). Note that all square brackets (`['s and `]'s) must be
|
||||
balanced; there is no mechanism provided for handling unbalanced
|
||||
square brackets.
|
||||
|
||||
`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 1-character string and
|
||||
pushed onto the stack. Otherwise the top-of-stack was a string,
|
||||
and the first character of that string is pushed back. (This
|
||||
command is a GNU extension.)
|
||||
|
||||
`x'
|
||||
Pops a value off the stack and executes it as a macro. Normally
|
||||
it should be a string; if it is a number, it is simply pushed back
|
||||
onto the stack. For example, `[1p]x' executes the macro `1p',
|
||||
which pushes 1 on the stack and prints `1' on a separate line.
|
||||
|
||||
Macros are most often stored in registers; `[1p]sa' stores a macro
|
||||
to print `1' into register `a', and `lax' invokes the macro.
|
||||
|
||||
`>R'
|
||||
Pops two values off the stack and compares them assuming they are
|
||||
numbers, executing the contents of register R as a macro if the
|
||||
original top-of-stack is greater. Thus, `1 2>a' will invoke
|
||||
register `a''s contents and `2 1>a' will not.
|
||||
|
||||
`!>R'
|
||||
Similar but invokes the macro if the original top-of-stack is not
|
||||
greater (is less than or equal to) what was the second-to-top.
|
||||
|
||||
`<R'
|
||||
Similar but invokes the macro if the original top-of-stack is less.
|
||||
|
||||
`!<R'
|
||||
Similar but invokes the macro if the original top-of-stack is not
|
||||
less (is greater than or equal to) what was the second-to-top.
|
||||
|
||||
`=R'
|
||||
Similar but invokes the macro if the two numbers popped are equal.
|
||||
|
||||
`!=R'
|
||||
Similar but invokes the macro if the two numbers popped are not
|
||||
equal.
|
||||
|
||||
`?'
|
||||
Reads a line from the terminal and executes it. This command
|
||||
allows a macro to request input from the user.
|
||||
|
||||
`q'
|
||||
During the execution of a macro, this command exits from the macro
|
||||
and also from the macro which invoked it. If called from the top
|
||||
level, or from a macro which was called directly from the top
|
||||
level, the `q' command will cause `dc' to exit.
|
||||
|
||||
`Q'
|
||||
Pops a value off the stack and uses it as a count of levels of
|
||||
macro execution to be exited. Thus, `3Q' exits three levels.
|
||||
|
||||
|
||||
File: dc.info, Node: Status Inquiry, Next: Miscellaneous, Prev: Strings, Up: Top
|
||||
|
||||
9 Status Inquiry
|
||||
****************
|
||||
|
||||
`Z'
|
||||
Pops a value off the stack, calculates the number of decimal
|
||||
digits it has (or number of characters, if it is a string) and
|
||||
pushes that number.
|
||||
|
||||
Note that the digit count for a number does _not_ include any
|
||||
leading zeros, even if those appear to the right of the radix
|
||||
point. This may seem a bit strange at first, but it is compatible
|
||||
with historical implementations of `dc', and can be argued to be
|
||||
useful for computing the magnitude of a value: `dSaXLaZ-' will
|
||||
compute the power-of-ten multiplier which would be needed to shift
|
||||
the decimal point to be immediately before the leftmost non-zero
|
||||
digit.
|
||||
|
||||
`X'
|
||||
Pops a value off the stack, calculates the number of fraction
|
||||
digits it has, and pushes that number. For a string, the value
|
||||
pushed is 0.
|
||||
|
||||
`z'
|
||||
Pushes the current stack depth: the number of objects on the stack
|
||||
before the execution of the `z' command.
|
||||
|
||||
|
||||
File: dc.info, Node: Miscellaneous, Next: Reporting bugs, Prev: Status Inquiry, Up: Top
|
||||
|
||||
10 Miscellaneous
|
||||
****************
|
||||
|
||||
`!'
|
||||
Will run the rest of the line as a system command. Note that
|
||||
parsing of the !<, !=, and !> commands take precedence, so if you
|
||||
want to run a command starting with <, =, or > you will need to
|
||||
add a space after the !.
|
||||
|
||||
`#'
|
||||
Will interpret the rest of the line as a comment. (This command
|
||||
is a GNU extension.)
|
||||
|
||||
`:R'
|
||||
Will pop the top two values off of the stack. The old
|
||||
second-to-top value will be stored in the array R, indexed by the
|
||||
old top-of-stack value.
|
||||
|
||||
`;R'
|
||||
Pops the top-of-stack and uses it as an index into the array R.
|
||||
The selected value is then pushed onto the stack.
|
||||
|
||||
Note that each stacked instance of a register has its own array
|
||||
associated with it. Thus `1 0:A 0SA 2 0:A LA 0;Ap' will print 1,
|
||||
because the 2 was stored in an instance of 0:A that was later popped.
|
||||
|
||||
|
||||
File: dc.info, Node: Reporting bugs, Prev: Miscellaneous, Up: Top
|
||||
|
||||
11 Reporting bugs
|
||||
*****************
|
||||
|
||||
Email bug reports to <bug-dc@gnu.org>.
|
||||
|
||||
|
||||
|
||||
Tag Table:
|
||||
Node: Top795
|
||||
Node: Introduction1965
|
||||
Node: Invocation3314
|
||||
Node: Printing Commands4165
|
||||
Node: Arithmetic6210
|
||||
Node: Stack Control9186
|
||||
Node: Registers10177
|
||||
Ref: Registers-Footnote-111242
|
||||
Node: Parameters11394
|
||||
Node: Strings12659
|
||||
Node: Status Inquiry15816
|
||||
Node: Miscellaneous16884
|
||||
Node: Reporting bugs17857
|
||||
|
||||
End Tag Table
|
|
@ -0,0 +1,556 @@
|
|||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename dc.info
|
||||
@settitle dc, an arbitrary precision calculator
|
||||
@c %**end of header
|
||||
|
||||
@include texi-ver.incl
|
||||
|
||||
@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
|
||||
|
||||
@direntry
|
||||
* dc: (dc). Arbitrary precision RPN ``Desktop Calculator''.
|
||||
@end direntry
|
||||
|
||||
@copying
|
||||
This manual documents version @value{DC_VERSION} of
|
||||
@sc{gnu} @command{dc}, an arbitrary precision calculator.
|
||||
|
||||
Copyright (C) 1984, 1994, 1997, 1998, 2000, 2005, 2006, 2008, 2013, 2016
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the @sc{gnu} Free Documentation License,
|
||||
Version 1.2 or any later version published by the Free Software Foundation;
|
||||
with no Invariant Sections, with no Front-Cover Texts,
|
||||
and with no Back-Cover Texts.
|
||||
A copy of the license can be found at
|
||||
@url{http://www.gnu.org/licenses/fdl.html} .
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@setchapternewpage off
|
||||
|
||||
@titlepage
|
||||
@title @sc{gnu} @code{dc}
|
||||
@subtitle an arbitrary precision calculator
|
||||
@subtitle version @value{DC_VERSION}
|
||||
@author by Ken Pizzini
|
||||
@author original manual by Richard Stallman
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
@end titlepage
|
||||
|
||||
@ifnottex
|
||||
@node Top
|
||||
@top GNU dc
|
||||
@insertcopying
|
||||
@end ifnottex
|
||||
|
||||
@menu
|
||||
* Introduction:: Introduction
|
||||
* Invocation:: Invocation
|
||||
* Printing Commands:: Printing Commands
|
||||
* Arithmetic:: Arithmetic
|
||||
* Stack Control:: Stack Control
|
||||
* Registers:: Registers
|
||||
* Parameters:: Parameters
|
||||
* Strings:: Strings
|
||||
* Status Inquiry:: Status Inquiry
|
||||
* Miscellaneous:: Other commands
|
||||
* Reporting bugs:: Reporting bugs
|
||||
@end menu
|
||||
|
||||
@node Introduction, Invocation, Top, Top
|
||||
@comment node-name, next, previous, up
|
||||
@chapter Introduction
|
||||
|
||||
@command{dc} is a reverse-polish desk calculator
|
||||
which supports unlimited precision arithmetic.
|
||||
It also allows you to define and call macros.
|
||||
Normally @command{dc} reads from the standard input;
|
||||
if any command arguments are given to it, they are filenames,
|
||||
and @command{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}
|
||||
(or whatever other keystroke your system uses to generate a @code{SIGINT})
|
||||
does not exit;
|
||||
it is used to abort macros that are looping, etc.
|
||||
|
||||
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 @command{dc}, type the digits (using upper
|
||||
case letters @code{A} through @code{F} as "digits" when working
|
||||
with input bases greater than ten),
|
||||
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
|
||||
|
||||
@command{dc} may be invoked with the following command-line options:
|
||||
@table @samp
|
||||
|
||||
@item -e @var{expr}
|
||||
@item --expression=@var{expr}
|
||||
Evaluate @var{expr} as @command{dc} commands.
|
||||
|
||||
@item -f @var{file}
|
||||
@item --file=@var{file}
|
||||
Read and evaluate @command{dc} commands from @var{file}.
|
||||
|
||||
@item -h
|
||||
@item --help
|
||||
Print a usage message summarizing the command-line options, then exit.
|
||||
|
||||
@item -V
|
||||
@item --version
|
||||
Print the version information for this program, then exit.
|
||||
@end table
|
||||
|
||||
If any command-line parameters remain after processing the options,
|
||||
these parameters are interpreted as additional @var{file}s whose
|
||||
contents are read and evaluated.
|
||||
A file name of @code{-} refers to the standard input stream.
|
||||
If no @code{-e} option was specified, and no files were specified,
|
||||
then the standard input will be read for commands to evaluate.
|
||||
|
||||
@node Printing Commands, Arithmetic, Invocation, Top
|
||||
@chapter Printing Commands
|
||||
|
||||
@table @samp
|
||||
@item p
|
||||
Prints the value on the top of the stack,
|
||||
without altering the stack.
|
||||
A newline is printed after the value.
|
||||
|
||||
@item n
|
||||
Prints the value on the top of the stack, popping it off,
|
||||
and does not print a newline after.
|
||||
(This command is a @sc{gnu} extension.)
|
||||
|
||||
@item P
|
||||
Pops off the value on top of the stack.
|
||||
If it it a string, it is simply printed without a trailing newline.
|
||||
Otherwise it is a number, and the integer portion of its absolute
|
||||
value is printed out as a "base (UCHAR_MAX+1)" byte stream.
|
||||
Assuming that (UCHAR_MAX+1) is 256
|
||||
(as it is on most machines with 8-bit bytes),
|
||||
the sequence
|
||||
@code{KSK0k1/ _1Ss[ls*]Sxd0>x
|
||||
[256~Ssd0<x]dsxx
|
||||
sx[q]Sq[Lsd0>qaPlxx]dsxx
|
||||
sx0sqLqsxLxLK+k}
|
||||
could also accomplish this function.
|
||||
(Much of the complexity of the above native-dc code is due
|
||||
to the ~ computing the characters backwards,
|
||||
and the desire to ensure that all registers wind up back
|
||||
in their original states.)
|
||||
(Details of the behavior with a number are a @sc{gnu} extension.
|
||||
Traditional @command{dc} happened to "support" similar functionality
|
||||
for a limited range of inputs as an accidental side-effect of its
|
||||
internal representation of numbers.)
|
||||
|
||||
@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
|
||||
|
||||
All numeric output is split to fit within 70 columns, by default.
|
||||
When a number is broken up in this way, the split is indicated
|
||||
by a "\" at the end of the to-be-continued output lines.
|
||||
The column width at which output is split can be overridden
|
||||
by setting the @var{DC_LINE_LENGTH} environment variable to
|
||||
the desired width.
|
||||
A @var{DC_LINE_LENGTH} of 0 (zero) disables the line-split
|
||||
feature altogether.
|
||||
Invalid values of @var{DC_LINE_LENGTH} are silently ignored.
|
||||
(The @var{DC_LINE_LENGTH} variable is a @sc{gnu} extension.)
|
||||
|
||||
@node Arithmetic, Stack Control, Printing Commands, Top
|
||||
@chapter Arithmetic
|
||||
|
||||
@table @samp
|
||||
@item +
|
||||
Pops two values off the stack, adds them, and pushes the result.
|
||||
The precision of the result is determined only
|
||||
by the values of the arguments, and is enough to be exact.
|
||||
|
||||
@item -
|
||||
Pops two values, subtracts the first one popped
|
||||
from the second one popped, and pushes the result.
|
||||
|
||||
@item *
|
||||
Pops two values, multiplies them, and pushes the result.
|
||||
The number of fraction digits in the result is the largest of
|
||||
the precision value,
|
||||
the number of fraction digits in the multiplier,
|
||||
or the number of fraction digits in the multiplicand;
|
||||
but in no event exceeding the number of digits required for
|
||||
an exact result.
|
||||
|
||||
@item /
|
||||
Pops two values, divides the second one popped
|
||||
from the first one popped, and pushes the result.
|
||||
The number of fraction digits is specified by the precision value.
|
||||
|
||||
@item %
|
||||
Pops two values,
|
||||
computes the remainder of the division that
|
||||
the @samp{/} command would do,
|
||||
and pushes that.
|
||||
The value computed is the same as that computed by
|
||||
the sequence @code{Sd dld/ Ld*-} .
|
||||
|
||||
@item ~
|
||||
Pops two values,
|
||||
divides the second one popped from the first one popped.
|
||||
The quotient is pushed first, and the remainder is pushed next.
|
||||
The number of fraction digits used in the division
|
||||
is specified by the precision value.
|
||||
(The sequence @code{SdSn lnld/ LnLd%} could also accomplish
|
||||
this function, with slightly different error checking.)
|
||||
(This command is a @sc{gnu} extension.)
|
||||
|
||||
@item ^
|
||||
Pops two values and exponentiates,
|
||||
using the first value popped as the exponent
|
||||
and the second popped as the base.
|
||||
The fraction part of the exponent is ignored.
|
||||
The precision value specifies the number of fraction
|
||||
digits in the result.
|
||||
|
||||
@item |
|
||||
Pops three values and computes a modular exponentiation.
|
||||
The first value popped is used as the reduction modulus;
|
||||
this value must be a non-zero number,
|
||||
and the result may not be accurate if the modulus
|
||||
is not an integer.
|
||||
The second popped is used as the exponent;
|
||||
this value must be a non-negative number,
|
||||
and any fractional part of this exponent will be ignored.
|
||||
The third value popped is the base which gets exponentiated,
|
||||
which should be an integer.
|
||||
For small integers this is like the sequence @code{Sm^Lm%},
|
||||
but, unlike @code{^},
|
||||
this command will work with arbitrarily large exponents.
|
||||
(This command is a @sc{gnu} extension.)
|
||||
|
||||
@item v
|
||||
Pops one value, computes its square root, and pushes that.
|
||||
The maximum of the precision value and the precision of the argument
|
||||
is used to determine the number of fraction digits in the result.
|
||||
@end table
|
||||
|
||||
Most arithmetic operations are affected by the @emph{precision value},
|
||||
which you can set with the @samp{k} command.
|
||||
The default precision value is zero,
|
||||
which means that all arithmetic except for
|
||||
addition and subtraction produces integer results.
|
||||
|
||||
@node Stack Control, Registers, Arithmetic, Top
|
||||
@chapter Stack Control
|
||||
|
||||
@table @samp
|
||||
@item c
|
||||
Clears the stack, rendering it empty.
|
||||
|
||||
@item d
|
||||
Duplicates the value on the top of the stack,
|
||||
pushing another copy of it.
|
||||
Thus, @samp{4d*p} computes 4 squared and prints it.
|
||||
|
||||
@item r
|
||||
Reverses the order of (swaps) the top two values on the stack.
|
||||
(This can also be accomplished with the sequence @code{SaSbLaLb}.)
|
||||
(This command is a @sc{gnu} extension.)
|
||||
|
||||
@item R
|
||||
Pops the top-of-stack as an integer @var{n}.
|
||||
Cyclically rotates the top @var{n} items on the updated stack.
|
||||
If @var{n} is positive,
|
||||
then the rotation direction will make the topmost
|
||||
element the second-from top;
|
||||
if @var{n} is negative,
|
||||
then the rotation will make the topmost element the
|
||||
@var{n}-th element from the top.
|
||||
If the stack depth is less than @var{n}
|
||||
then the entire stack is rotated (in the appropriate direction),
|
||||
without any error being reported.
|
||||
(This command is a @sc{gnu} extension.)
|
||||
@end table
|
||||
|
||||
@node Registers, Parameters, Stack Control, Top
|
||||
@chapter Registers
|
||||
|
||||
@command{dc} provides at least 256 memory registers@footnote{The
|
||||
exact number of registers provided by @command{dc} depends
|
||||
on the range of an @code{unsigned char} in the C compiler
|
||||
used to create the @command{dc} executable.},
|
||||
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.
|
||||
The value @code{0} is retrieved if the
|
||||
register is uninitialized or its stack has become empty.
|
||||
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
|
||||
|
||||
@command{dc} has three parameters that control its operation:
|
||||
the precision, the input radix, and the output radix.
|
||||
The precision specifies the number of fraction digits
|
||||
to keep in the result of most arithmetic operations.
|
||||
The input radix controls the interpretation of numbers typed in;
|
||||
@emph{all} numbers typed in use this radix.
|
||||
The output radix is used for printing numbers.
|
||||
|
||||
The input and output radices are separate parameters;
|
||||
you can make them unequal, which can be useful or confusing.
|
||||
The input radix must be between 2 and 16 inclusive.
|
||||
The output radix must be at least 2.
|
||||
The precision must be zero or greater.
|
||||
The precision is always measured in decimal digits,
|
||||
regardless of the current input or output radix.
|
||||
|
||||
@table @samp
|
||||
@item i
|
||||
Pops the value off the top of the stack
|
||||
and uses it to set the input radix.
|
||||
|
||||
@item o
|
||||
Pops the value off the top of the stack
|
||||
and uses it to set the output radix.
|
||||
|
||||
@item k
|
||||
Pops the value off the top of the stack
|
||||
and uses it to set the precision.
|
||||
|
||||
@item I
|
||||
Pushes the current input radix on the stack.
|
||||
|
||||
@item O
|
||||
Pushes the current output radix on the stack.
|
||||
|
||||
@item K
|
||||
Pushes the current precision on the stack.
|
||||
|
||||
@end table
|
||||
|
||||
@node Strings, Status Inquiry, Parameters, Top
|
||||
@chapter Strings
|
||||
|
||||
@command{dc} has a limited ability
|
||||
to 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 @command{dc} commands).
|
||||
Both registers and the stack can hold strings,
|
||||
and @command{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).
|
||||
Note that all square brackets (@samp{[}s and @samp{]}s) must be balanced;
|
||||
there is no mechanism provided for handling unbalanced square brackets.
|
||||
|
||||
@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 1-character 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 @sc{gnu} extension.)
|
||||
|
||||
@item x
|
||||
Pops a value off the stack and executes it as a macro.
|
||||
Normally it should be a string;
|
||||
if it is a number, it is simply pushed back onto the stack.
|
||||
For example, @samp{[1p]x} executes the macro @samp{1p},
|
||||
which pushes 1 on the stack and prints @samp{1} on a separate line.
|
||||
|
||||
Macros are most often stored in registers;
|
||||
@samp{[1p]sa} stores a macro to print @samp{1} into register @samp{a},
|
||||
and @samp{lax} invokes the macro.
|
||||
|
||||
@item >@var{r}
|
||||
Pops two values off the stack and compares them
|
||||
assuming they are numbers,
|
||||
executing the contents of register @var{r} as a macro
|
||||
if the original top-of-stack is greater.
|
||||
Thus, @samp{1 2>a} will invoke register @samp{a}'s contents
|
||||
and @samp{2 1>a} will not.
|
||||
|
||||
@item !>@var{r}
|
||||
Similar but invokes the macro if the original top-of-stack is not greater
|
||||
(is less than or equal to) what was the second-to-top.
|
||||
|
||||
@item <@var{r}
|
||||
Similar but invokes the macro if the original top-of-stack is less.
|
||||
|
||||
@item !<@var{r}
|
||||
Similar but invokes the macro if the original top-of-stack is not less
|
||||
(is greater than or equal to) what was the second-to-top.
|
||||
|
||||
@item =@var{r}
|
||||
Similar but invokes the macro if the two numbers popped are equal.
|
||||
@c This can also be validly used to compare two strings for equality.
|
||||
|
||||
@item !=@var{r}
|
||||
Similar but invokes the macro if the two numbers popped are not equal.
|
||||
@c This can also be validly used to compare two strings for equality.
|
||||
|
||||
@item ?
|
||||
Reads a line from the terminal and executes it.
|
||||
This command allows a macro to request input from the user.
|
||||
|
||||
@item q
|
||||
During the execution of a macro,
|
||||
this command exits from the macro and also from the macro which invoked it.
|
||||
If called from the top level,
|
||||
or from a macro which was called directly from the top level,
|
||||
the @samp{q} command will cause @command{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 decimal digits it has
|
||||
(or number of characters, if it is a string)
|
||||
and pushes that number.
|
||||
|
||||
Note that the digit count for a number does
|
||||
@emph{not} include any leading zeros,
|
||||
even if those appear to the right of the radix point.
|
||||
This may seem a bit strange at first,
|
||||
but it is compatible with historical implementations of @command{dc},
|
||||
and can be argued to be useful for computing the magnitude of a value:
|
||||
@code{dSaXLaZ-} will compute the power-of-ten multiplier
|
||||
which would be needed to shift the decimal point
|
||||
to be immediately before the leftmost non-zero digit.
|
||||
|
||||
@item X
|
||||
Pops a value off the stack,
|
||||
calculates the number of fraction digits it has,
|
||||
and pushes that number.
|
||||
For a string, the value pushed is
|
||||
@c -1.
|
||||
0.
|
||||
|
||||
@item z
|
||||
Pushes the current stack depth:
|
||||
the number of objects on the stack
|
||||
before the execution of the @samp{z} command.
|
||||
@end table
|
||||
|
||||
@node Miscellaneous, Reporting bugs, Status Inquiry, Top
|
||||
@chapter Miscellaneous
|
||||
|
||||
@table @samp
|
||||
@item !
|
||||
Will run the rest of the line as a system command.
|
||||
Note that parsing of the !<, !=, and !> commands take precedence,
|
||||
so if you want to run a command starting with <, =, or > you will
|
||||
need to add a space after the !.
|
||||
|
||||
@item #
|
||||
Will interpret the rest of the line as a comment.
|
||||
(This command is a @sc{gnu} extension.)
|
||||
|
||||
@item :@var{r}
|
||||
Will pop the top two values off of the stack.
|
||||
The old second-to-top value will be stored in the array @var{r},
|
||||
indexed by the old top-of-stack value.
|
||||
|
||||
@item ;@var{r}
|
||||
Pops the top-of-stack and uses it as an index into
|
||||
the array @var{r}.
|
||||
The selected value is then pushed onto the stack.
|
||||
@end table
|
||||
|
||||
Note that each stacked instance of a register has its own
|
||||
array associated with it.
|
||||
Thus @samp{1 @var{0:a} 0S@var{a} 2 @var{0:a} L@var{a} @var{0;a}p}
|
||||
will print 1, because the 2 was stored in an instance of @var{0:a}
|
||||
that was later popped.
|
||||
|
||||
@node Reporting bugs, , Miscellaneous, Top
|
||||
@chapter Reporting bugs
|
||||
|
||||
Email bug reports to @email{bug-dc@@gnu.org}.
|
||||
@contents
|
||||
@bye
|
|
@ -0,0 +1,2 @@
|
|||
@set BC_VERSION @BC_VERSION@
|
||||
@set DC_VERSION @DC_VERSION@
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,169 @@
|
|||
/* Declarations for getopt.
|
||||
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
|
||||
1999, 2001, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
|
||||
#ifndef __need_getopt
|
||||
# define _GETOPT_H 1
|
||||
#endif
|
||||
|
||||
/* If __GNU_LIBRARY__ is not already defined, either we are being used
|
||||
standalone, or this is the first header included in the source file.
|
||||
If we are being used with glibc, we need to include <features.h>, but
|
||||
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
|
||||
not defined, include <ctype.h>, which will pull in <features.h> for us
|
||||
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
|
||||
doesn't flood the namespace with stuff the way some other headers do.) */
|
||||
#if !defined __GNU_LIBRARY__
|
||||
# include <ctype.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns -1, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
#ifndef __need_getopt
|
||||
/* 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
|
||||
{
|
||||
const char *name;
|
||||
/* 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
|
||||
#endif /* need getopt */
|
||||
|
||||
|
||||
/* Get definitions and prototypes for functions to process the
|
||||
arguments in ARGV (ARGC of them, minus the program name) for
|
||||
options given in OPTS.
|
||||
|
||||
Return the option character from OPTS just read. Return -1 when
|
||||
there are no more options. For unrecognized options, or options
|
||||
missing arguments, `optopt' is set to the option letter, and '?' is
|
||||
returned.
|
||||
|
||||
The OPTS string is a list of characters which are recognized option
|
||||
letters, optionally followed by colons, specifying that that letter
|
||||
takes an argument, to be placed in `optarg'.
|
||||
|
||||
If a letter in OPTS is followed by two colons, its argument is
|
||||
optional. This behavior is specific to the GNU `getopt'.
|
||||
|
||||
The argument `--' causes premature termination of argument
|
||||
scanning, explicitly telling `getopt' that there are no more
|
||||
options.
|
||||
|
||||
If OPTS begins with `--', then non-option arguments are treated as
|
||||
arguments to the option '\0'. This behavior is specific to the GNU
|
||||
`getopt'. */
|
||||
|
||||
#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__ */
|
||||
|
||||
#ifndef __need_getopt
|
||||
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);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure we later can get all the definitions and declarations. */
|
||||
#undef __need_getopt
|
||||
|
||||
#endif /* getopt.h */
|
|
@ -0,0 +1,143 @@
|
|||
/* number.h: Arbitrary precision numbers header file. */
|
||||
/*
|
||||
Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000, 2012-2017 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 3 of the License , or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to:
|
||||
|
||||
The Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor
|
||||
Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _NUMBER_H_
|
||||
#define _NUMBER_H_
|
||||
|
||||
typedef enum {PLUS, MINUS} sign;
|
||||
|
||||
typedef struct bc_struct *bc_num;
|
||||
|
||||
typedef struct bc_struct
|
||||
{
|
||||
sign n_sign;
|
||||
int n_len; /* The number of digits before the decimal point. */
|
||||
int n_scale; /* The number of digits after the decimal point. */
|
||||
int n_refs; /* The number of pointers to this number. */
|
||||
bc_num n_next; /* Linked list for available list. */
|
||||
char *n_ptr; /* The pointer to the actual storage.
|
||||
If NULL, n_value points to the inside of
|
||||
another number (bc_multiply...) and should
|
||||
not be "freed." */
|
||||
char *n_value; /* The number. Not zero char terminated.
|
||||
May not point to the same place as n_ptr as
|
||||
in the case of leading zeros generated. */
|
||||
} bc_struct;
|
||||
|
||||
|
||||
/* The base used in storing the numbers in n_value above.
|
||||
Currently this MUST be 10. */
|
||||
|
||||
#define BASE 10
|
||||
|
||||
/* Some useful macros and constants. */
|
||||
|
||||
#define CH_VAL(c) (c - '0')
|
||||
#define BCD_CHAR(d) (d + '0')
|
||||
|
||||
#ifdef MIN
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#endif
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a,b) ((a)>(b)?(b):(a))
|
||||
#define ODD(a) ((a)&1)
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef LONG_MAX
|
||||
#define LONG_MAX 0x7fffffff
|
||||
#endif
|
||||
|
||||
|
||||
/* Global numbers. */
|
||||
extern bc_num _zero_;
|
||||
extern bc_num _one_;
|
||||
extern bc_num _two_;
|
||||
|
||||
|
||||
/* Function Prototypes */
|
||||
|
||||
void bc_init_numbers (void);
|
||||
|
||||
bc_num bc_new_num (int length, int scale);
|
||||
|
||||
void bc_free_num (bc_num *num);
|
||||
|
||||
bc_num bc_copy_num (bc_num num);
|
||||
|
||||
void bc_init_num (bc_num *num);
|
||||
|
||||
void bc_str2num (bc_num *num, char *str, int scale);
|
||||
|
||||
char *bc_num2str (bc_num num);
|
||||
|
||||
void bc_int2num (bc_num *num, int val);
|
||||
|
||||
long bc_num2long (bc_num num);
|
||||
|
||||
int bc_compare (bc_num n1, bc_num n2);
|
||||
|
||||
char bc_is_zero (bc_num num);
|
||||
|
||||
char bc_is_near_zero (bc_num num, int scale);
|
||||
|
||||
char bc_is_neg (bc_num num);
|
||||
|
||||
void bc_add (bc_num n1, bc_num n2, bc_num *result, int scale_min);
|
||||
|
||||
void bc_sub (bc_num n1, bc_num n2, bc_num *result, int scale_min);
|
||||
|
||||
void bc_multiply (bc_num n1, bc_num n2, bc_num *prod, int scale);
|
||||
|
||||
int bc_divide (bc_num n1, bc_num n2, bc_num *quot, int scale);
|
||||
|
||||
int bc_modulo (bc_num num1, bc_num num2, bc_num *result, int scale);
|
||||
|
||||
int bc_divmod (bc_num num1, bc_num num2, bc_num *quot,
|
||||
bc_num *rem, int scale);
|
||||
|
||||
int bc_raisemod (bc_num base, bc_num expo, bc_num mod,
|
||||
bc_num *result, int scale);
|
||||
|
||||
void bc_raise (bc_num num1, bc_num num2, bc_num *result,
|
||||
int scale);
|
||||
|
||||
int bc_sqrt (bc_num *num, int scale);
|
||||
|
||||
void bc_out_num (bc_num num, int o_base, void (* out_char)(int),
|
||||
int leading_zero);
|
||||
|
||||
void bc_out_long (long val, int size, int space, void (*out_char)(int));
|
||||
#endif
|
|
@ -0,0 +1,301 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# $NetBSD: install-sh.in,v 1.6 2012/01/11 13:07:31 hans Exp $
|
||||
# This script now also installs multiple files, but might choke on installing
|
||||
# multiple files with spaces in the file names.
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# 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.
|
||||
|
||||
awkprog="${AWKPROG-awk}"
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
instcmd="$cpprog"
|
||||
instflags=""
|
||||
pathcompchmodcmd="$chmodprog 755"
|
||||
chmodcmd="$chmodprog 755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
stripflags=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
msrc=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
suffix=""
|
||||
suffixfmt=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-b) suffix=".old"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-B) suffixfmt="$2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m*)
|
||||
chmodcmd="$chmodprog ${1#-m}"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-S) stripcmd="$stripprog"
|
||||
stripflags="-S $2 $stripflags"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-p) instflags="-p"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$msrc" = x ]
|
||||
then
|
||||
msrc="$dst"
|
||||
else
|
||||
msrc="$msrc $dst"
|
||||
fi
|
||||
src="$dst"
|
||||
dst="$1"
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$dir_arg" = x ]
|
||||
then
|
||||
dstisfile=""
|
||||
if [ ! -d "$dst" ]
|
||||
then
|
||||
if [ x"$msrc" = x"$src" ]
|
||||
then
|
||||
dstisfile=true
|
||||
else
|
||||
echo "install: destination is not a directory"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
msrc="$msrc $dst"
|
||||
fi
|
||||
|
||||
if [ x"$msrc" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for srcarg in $msrc; do
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
|
||||
dstarg="$srcarg"
|
||||
else
|
||||
dstarg="$dst"
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $srcarg $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f "$srcarg" ]
|
||||
then
|
||||
doinst="$instcmd $instflags"
|
||||
elif [ -d "$srcarg" ]
|
||||
then
|
||||
echo "install: $srcarg: not a regular file"
|
||||
exit 1
|
||||
elif [ "$srcarg" = "/dev/null" ]
|
||||
then
|
||||
doinst="$cpprog"
|
||||
else
|
||||
echo "install: $srcarg does not exist"
|
||||
exit 1
|
||||
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 "$dstarg" ]
|
||||
then
|
||||
dstarg="$dstarg"/`basename "$srcarg"`
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo "$dstarg" | 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
|
||||
$doit $mkdirprog "${pathcomp}"
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "${pathcomp}"; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "${pathcomp}"; else true ; fi &&
|
||||
if [ x"$pathcompchmodcmd" != x ]; then $doit $pathcompchmodcmd "${pathcomp}"; else true ; fi
|
||||
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
if [ -d "$dstarg" ]; then
|
||||
true
|
||||
else
|
||||
$doit $mkdirprog "$dstarg" &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dstarg"; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dstarg"; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dstarg"; else true ; fi
|
||||
fi
|
||||
else
|
||||
|
||||
if [ x"$dstisfile" = x ]
|
||||
then
|
||||
file=$srcarg
|
||||
else
|
||||
file=$dst
|
||||
fi
|
||||
|
||||
dstfile=`basename "$file"`
|
||||
dstfinal="$dstdir/$dstfile"
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Make a backup file name in the proper directory.
|
||||
case x$suffixfmt in
|
||||
*%*) suffix=`echo x |
|
||||
$awkprog -v bname="$dstfinal" -v fmt="$suffixfmt" '
|
||||
{ cnt = 0;
|
||||
do {
|
||||
sfx = sprintf(fmt, cnt++);
|
||||
name = bname sfx;
|
||||
} while (system("test -f " name) == 0);
|
||||
print sfx; }' -`;;
|
||||
x) ;;
|
||||
*) suffix="$suffixfmt";;
|
||||
esac
|
||||
dstbackup="$dstfinal$suffix"
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $doinst $srcarg "$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 $stripflags "$dsttmp"; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
if [ x"$suffix" != x ] && [ -f "$dstfinal" ]
|
||||
then
|
||||
$doit $mvcmd "$dstfinal" "$dstbackup"
|
||||
else
|
||||
$doit $rmcmd -f "$dstfinal"
|
||||
fi &&
|
||||
$doit $mvcmd "$dsttmp" "$dstfinal"
|
||||
fi
|
||||
|
||||
done &&
|
||||
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,26 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
noinst_LIBRARIES = libbc.a
|
||||
|
||||
AM_CPPFLAGS = -I. -I.. -I$(srcdir)/../h
|
||||
|
||||
libbc_a_SOURCES = getopt.c getopt1.c vfprintf.c number.c
|
||||
|
||||
DEFS = @DEFS@ $(DEFSADD)
|
||||
|
||||
AM_CFLAGS = @CFLAGS@
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in number.c
|
||||
CLEANFILES = testmul specialnumber muldigits.h
|
||||
|
||||
newnumber.o: number.c muldigits.h
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -DMULDIGITS -o newnumber.o $(srcdir)/number.c
|
||||
|
||||
muldigits.h: testmul
|
||||
@echo "The following may take up to 10 minutes."
|
||||
./testmul > muldigits.h
|
||||
|
||||
testmul: testmul.o number.o
|
||||
$(CC) $(CFLAGS) -o testmul testmul.o number.o
|
||||
|
||||
specialnumber: newnumber.o
|
||||
cp newnumber.o number.o
|
|
@ -0,0 +1,546 @@
|
|||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = lib
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/depcomp
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
AM_V_AR = $(am__v_AR_@AM_V@)
|
||||
am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
|
||||
am__v_AR_0 = @echo " AR " $@;
|
||||
am__v_AR_1 =
|
||||
libbc_a_AR = $(AR) $(ARFLAGS)
|
||||
libbc_a_LIBADD =
|
||||
am_libbc_a_OBJECTS = getopt.$(OBJEXT) getopt1.$(OBJEXT) \
|
||||
vfprintf.$(OBJEXT) number.$(OBJEXT)
|
||||
libbc_a_OBJECTS = $(am_libbc_a_OBJECTS)
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(libbc_a_SOURCES)
|
||||
DIST_SOURCES = $(libbc_a_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
BC_VERSION = @BC_VERSION@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DC_VERSION = @DC_VERSION@
|
||||
DEFS = @DEFS@ $(DEFSADD)
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LEX = @LEX@
|
||||
LEXLIB = @LEXLIB@
|
||||
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
READLINELIB = @READLINELIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
YACC = @YACC@
|
||||
YFLAGS = @YFLAGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
noinst_LIBRARIES = libbc.a
|
||||
AM_CPPFLAGS = -I. -I.. -I$(srcdir)/../h
|
||||
libbc_a_SOURCES = getopt.c getopt1.c vfprintf.c number.c
|
||||
AM_CFLAGS = @CFLAGS@
|
||||
MAINTAINERCLEANFILES = Makefile.in number.c
|
||||
CLEANFILES = testmul specialnumber muldigits.h
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu lib/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
|
||||
libbc.a: $(libbc_a_OBJECTS) $(libbc_a_DEPENDENCIES) $(EXTRA_libbc_a_DEPENDENCIES)
|
||||
$(AM_V_at)-rm -f libbc.a
|
||||
$(AM_V_AR)$(libbc_a_AR) libbc.a $(libbc_a_OBJECTS) $(libbc_a_LIBADD)
|
||||
$(AM_V_at)$(RANLIB) libbc.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/number.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfprintf.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
|
||||
distclean-compile distclean-generic distclean-tags distdir dvi \
|
||||
dvi-am html html-am info info-am install install-am \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am
|
||||
|
||||
|
||||
newnumber.o: number.c muldigits.h
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -DMULDIGITS -o newnumber.o $(srcdir)/number.c
|
||||
|
||||
muldigits.h: testmul
|
||||
@echo "The following may take up to 10 minutes."
|
||||
./testmul > muldigits.h
|
||||
|
||||
testmul: testmul.o number.o
|
||||
$(CC) $(CFLAGS) -o testmul testmul.o number.o
|
||||
|
||||
specialnumber: newnumber.o
|
||||
cp newnumber.o number.o
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,185 @@
|
|||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
|
||||
Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996,
|
||||
1997, 1998, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <getopt.h>
|
||||
#else
|
||||
# include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
|
||||
#include <gnu-versions.h>
|
||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
#define ELIDE_CODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ELIDE_CODE
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (int argc,
|
||||
char *const *argv,
|
||||
const char *options,
|
||||
const struct option *long_options,
|
||||
int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (int argc,
|
||||
char *const *argv,
|
||||
const char *options,
|
||||
const struct option *long_options,
|
||||
int *opt_index)
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
# ifdef _LIBC
|
||||
libc_hidden_def (getopt_long)
|
||||
libc_hidden_def (getopt_long_only)
|
||||
# endif
|
||||
|
||||
#endif /* Not ELIDE_CODE. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,246 @@
|
|||
/* compute the crossover for recursive and simple multiplication */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "number.h"
|
||||
#ifndef VARARGS
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
/* from number.c ... */
|
||||
extern int mul_base_digits;
|
||||
/* extern int mul_small_digits; */
|
||||
extern bc_num _one_;
|
||||
|
||||
/* global variables */
|
||||
int test_n = 1000;
|
||||
long test_time = 30 * CLOCKS_PER_SEC; /* 30 seconds */
|
||||
|
||||
/* Other things for number.c. */
|
||||
int std_only;
|
||||
|
||||
void
|
||||
out_of_memory()
|
||||
{
|
||||
fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Runtime error will print a message and stop the machine. */
|
||||
|
||||
#ifndef VARARGS
|
||||
#ifdef __STDC__
|
||||
void
|
||||
rt_error (char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
rt_error (mesg)
|
||||
char *mesg;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
rt_error (mesg, va_alist)
|
||||
char *mesg;
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
char error_mesg [255];
|
||||
|
||||
#ifndef VARARGS
|
||||
va_start (args, mesg);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
vsprintf (error_mesg, mesg, args);
|
||||
va_end (args);
|
||||
|
||||
fprintf (stderr, "Runtime error: %s\n", error_mesg);
|
||||
}
|
||||
|
||||
/* A runtime warning tells of some action taken by the processor that
|
||||
may change the program execution but was not enough of a problem
|
||||
to stop the execution. */
|
||||
|
||||
#ifndef VARARGS
|
||||
#ifdef __STDC__
|
||||
void
|
||||
rt_warn (char *mesg, ...)
|
||||
#else
|
||||
void
|
||||
rt_warn (mesg)
|
||||
char *mesg;
|
||||
#endif
|
||||
#else
|
||||
void
|
||||
rt_warn (mesg, va_alist)
|
||||
char *mesg;
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
char error_mesg [255];
|
||||
|
||||
#ifndef VARARGS
|
||||
va_start (args, mesg);
|
||||
#else
|
||||
va_start (args);
|
||||
#endif
|
||||
vsprintf (error_mesg, mesg, args);
|
||||
va_end (args);
|
||||
|
||||
fprintf (stderr, "Runtime warning: %s\n", error_mesg);
|
||||
}
|
||||
|
||||
void
|
||||
out_char (int ch)
|
||||
{
|
||||
putchar (ch);
|
||||
}
|
||||
|
||||
/* Time stuff !!! */
|
||||
|
||||
int
|
||||
timeit ( bc_num a, bc_num b, int *n)
|
||||
{
|
||||
clock_t first;
|
||||
int i, res;
|
||||
bc_num c;
|
||||
|
||||
bc_init_num (&c);
|
||||
first = clock();
|
||||
*n = 0;
|
||||
do {
|
||||
for (i=0; i<test_n; i++)
|
||||
bc_multiply(a,b,&c,0);
|
||||
*n += test_n;
|
||||
res = (int) (clock() - first);
|
||||
} while (res < test_time);
|
||||
return res;
|
||||
}
|
||||
|
||||
int debug = 0; /* Print debugging messages? */
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
bc_num ten, num, expo, big;
|
||||
|
||||
int min, max, mid;
|
||||
|
||||
#if 0
|
||||
int smallsize;
|
||||
#endif
|
||||
|
||||
int n1, n2;
|
||||
clock_t t1, t2;
|
||||
float permul1, permul2;
|
||||
|
||||
/* args? */
|
||||
if (argc > 1)
|
||||
if (strcmp (argv[1], "-d") == 0)
|
||||
debug = 1;
|
||||
|
||||
bc_init_numbers();
|
||||
bc_init_num (&ten);
|
||||
bc_init_num (&num);
|
||||
bc_init_num (&expo);
|
||||
bc_init_num (&big);
|
||||
bc_int2num (&ten, 10);
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "Timings are for %d multiplies\n"
|
||||
"Minimum time is %lu seconds\n", test_n,
|
||||
test_time/CLOCKS_PER_SEC);
|
||||
|
||||
/* Two of the same size */
|
||||
min = 10;
|
||||
max = 500;
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "Testing numbers of the same length.\n");
|
||||
|
||||
while (min < max) {
|
||||
mid = (min+max)/2;
|
||||
if (debug) fprintf (stderr,"Checking %d...\n", mid);
|
||||
|
||||
bc_int2num (&expo, mid);
|
||||
bc_raise (ten, expo, &num, 0);
|
||||
bc_sub (num, _one_, &num, 0);
|
||||
|
||||
mul_base_digits = 2*mid+1;
|
||||
t1 = timeit (num, num, &n1);
|
||||
permul1 = (float)t1/(float)n1;
|
||||
|
||||
mul_base_digits = 2*mid-1;
|
||||
t2 = timeit (num, num, &n2);
|
||||
permul2 = (float)t2/(float)n2;
|
||||
|
||||
if (permul1 < permul2)
|
||||
min = mid+1;
|
||||
else
|
||||
max = mid-1;
|
||||
|
||||
if (debug) {
|
||||
fprintf (stderr, "n1 = %d :: n2 = %d\n", n1, n2);
|
||||
fprintf (stderr, "p1 = %f :: p2 = %f\n", permul1, permul2);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "Base digits crossover at %d digits\n", min);
|
||||
printf ("#define MUL_BASE_DIGITS %d\n", 2*min);
|
||||
|
||||
|
||||
#if 0
|
||||
mul_base_digits = min;
|
||||
|
||||
/* Small one times a big one. */
|
||||
|
||||
smallsize = min/2;
|
||||
bc_int2num (&expo, smallsize);
|
||||
bc_raise (ten, expo, &big, 0);
|
||||
bc_sub (num, _one_, &big, 0);
|
||||
|
||||
min = min / 2;
|
||||
max = 500;
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "Testing numbers of the different length.\n");
|
||||
|
||||
while (min < max) {
|
||||
mid = (min+max)/2;
|
||||
if (debug) fprintf (stderr, "Checking %d...\n", mid);
|
||||
|
||||
bc_int2num (&expo, mid-smallsize);
|
||||
bc_raise (ten, expo, &num, 0);
|
||||
bc_sub (num, _one_, &num, 0);
|
||||
|
||||
mul_small_digits = mid+1;
|
||||
t1 = timeit (big, num, &n1);
|
||||
permul1 = (float)t1/(float)n1;
|
||||
|
||||
mul_small_digits = mid-1;
|
||||
t2 = timeit (big, num, &n2);
|
||||
permul2 = (float)t2/(float)n2;
|
||||
|
||||
if (permul1 < permul2)
|
||||
min = mid+1;
|
||||
else
|
||||
max = mid-1;
|
||||
|
||||
if (debug) {
|
||||
fprintf (stderr, "n1 = %d :: n2 = %d\n", n1, n2);
|
||||
fprintf (stderr, "p1 = %f :: p2 = %f\n", permul1, permul2);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "Non equal digits crossover at %d total digits\n", min);
|
||||
printf ("#define MUL_SMALL_DIGITS = %d\n", min);
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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 */
|
|
@ -0,0 +1,215 @@
|
|||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2013-10-28.13; # UTC
|
||||
|
||||
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal autoconf autoheader autom4te automake makeinfo
|
||||
bison yacc flex lex help2man
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=http://www.perl.org/
|
||||
flex_URL=http://flex.sourceforge.net/
|
||||
gnu_software_URL=http://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
case $normalized_program in
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified 'configure.ac',"
|
||||
echo "or m4 files included by it."
|
||||
program_details 'autoconf'
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified 'acconfig.h' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'autoheader'
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified 'Makefile.am' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'automake'
|
||||
;;
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'aclocal'
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
program_details 'autom4te'
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,247 @@
|
|||
#! /bin/sh
|
||||
# ylwrap - wrapper for lex/yacc invocations.
|
||||
|
||||
scriptversion=2013-01-12.17; # UTC
|
||||
|
||||
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
|
||||
#
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
get_dirname ()
|
||||
{
|
||||
case $1 in
|
||||
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
|
||||
# Otherwise, we want the empty string (not ".").
|
||||
esac
|
||||
}
|
||||
|
||||
# guard FILE
|
||||
# ----------
|
||||
# The CPP macro used to guard inclusion of FILE.
|
||||
guard ()
|
||||
{
|
||||
printf '%s\n' "$1" \
|
||||
| sed \
|
||||
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
|
||||
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
|
||||
-e 's/__*/_/g'
|
||||
}
|
||||
|
||||
# quote_for_sed [STRING]
|
||||
# ----------------------
|
||||
# Return STRING (or stdin) quoted to be used as a sed pattern.
|
||||
quote_for_sed ()
|
||||
{
|
||||
case $# in
|
||||
0) cat;;
|
||||
1) printf '%s\n' "$1";;
|
||||
esac \
|
||||
| sed -e 's|[][\\.*]|\\&|g'
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'')
|
||||
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
--basedir)
|
||||
basedir=$2
|
||||
shift 2
|
||||
;;
|
||||
-h|--h*)
|
||||
cat <<\EOF
|
||||
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
|
||||
|
||||
Wrapper for lex/yacc invocations, renaming files as desired.
|
||||
|
||||
INPUT is the input file
|
||||
OUTPUT is one file PROG generates
|
||||
DESIRED is the file we actually want instead of OUTPUT
|
||||
PROGRAM is program to run
|
||||
ARGS are passed to PROG
|
||||
|
||||
Any number of OUTPUT,DESIRED pairs may be used.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v|--v*)
|
||||
echo "ylwrap $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# The input.
|
||||
input=$1
|
||||
shift
|
||||
# We'll later need for a correct munging of "#line" directives.
|
||||
input_sub_rx=`get_dirname "$input" | quote_for_sed`
|
||||
case $input in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
# Absolute path; do nothing.
|
||||
;;
|
||||
*)
|
||||
# Relative path. Make it absolute.
|
||||
input=`pwd`/$input
|
||||
;;
|
||||
esac
|
||||
input_rx=`get_dirname "$input" | quote_for_sed`
|
||||
|
||||
# Since DOS filename conventions don't allow two dots,
|
||||
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
|
||||
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
|
||||
y_tab_nodot=false
|
||||
if test -f y_tab.c || test -f y_tab.h; then
|
||||
y_tab_nodot=true
|
||||
fi
|
||||
|
||||
# The parser itself, the first file, is the destination of the .y.c
|
||||
# rule in the Makefile.
|
||||
parser=$1
|
||||
|
||||
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
|
||||
# instance, we rename #include "y.tab.h" into #include "parse.h"
|
||||
# during the conversion from y.tab.c to parse.c.
|
||||
sed_fix_filenames=
|
||||
|
||||
# Also rename header guards, as Bison 2.7 for instance uses its header
|
||||
# guard in its implementation file.
|
||||
sed_fix_header_guards=
|
||||
|
||||
while test $# -ne 0; do
|
||||
if test x"$1" = x"--"; then
|
||||
shift
|
||||
break
|
||||
fi
|
||||
from=$1
|
||||
# Handle y_tab.c and y_tab.h output by DOS
|
||||
if $y_tab_nodot; then
|
||||
case $from in
|
||||
"y.tab.c") from=y_tab.c;;
|
||||
"y.tab.h") from=y_tab.h;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
to=$1
|
||||
shift
|
||||
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
|
||||
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
|
||||
done
|
||||
|
||||
# The program to run.
|
||||
prog=$1
|
||||
shift
|
||||
# Make any relative path in $prog absolute.
|
||||
case $prog in
|
||||
[\\/]* | ?:[\\/]*) ;;
|
||||
*[\\/]*) prog=`pwd`/$prog ;;
|
||||
esac
|
||||
|
||||
dirname=ylwrap$$
|
||||
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
mkdir $dirname || exit 1
|
||||
|
||||
cd $dirname
|
||||
|
||||
case $# in
|
||||
0) "$prog" "$input" ;;
|
||||
*) "$prog" "$@" "$input" ;;
|
||||
esac
|
||||
ret=$?
|
||||
|
||||
if test $ret -eq 0; then
|
||||
for from in *
|
||||
do
|
||||
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
|
||||
if test -f "$from"; then
|
||||
# If $2 is an absolute path name, then just use that,
|
||||
# otherwise prepend '../'.
|
||||
case $to in
|
||||
[\\/]* | ?:[\\/]*) target=$to;;
|
||||
*) target=../$to;;
|
||||
esac
|
||||
|
||||
# Do not overwrite unchanged header files to avoid useless
|
||||
# recompilations. Always update the parser itself: it is the
|
||||
# destination of the .y.c rule in the Makefile. Divert the
|
||||
# output of all other files to a temporary file so we can
|
||||
# compare them to existing versions.
|
||||
if test $from != $parser; then
|
||||
realtarget=$target
|
||||
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
|
||||
fi
|
||||
|
||||
# Munge "#line" or "#" directives. Don't let the resulting
|
||||
# debug information point at an absolute srcdir. Use the real
|
||||
# output file name, not yy.lex.c for instance. Adjust the
|
||||
# include guards too.
|
||||
sed -e "/^#/!b" \
|
||||
-e "s|$input_rx|$input_sub_rx|" \
|
||||
-e "$sed_fix_filenames" \
|
||||
-e "$sed_fix_header_guards" \
|
||||
"$from" >"$target" || ret=$?
|
||||
|
||||
# Check whether files must be updated.
|
||||
if test "$from" != "$parser"; then
|
||||
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
|
||||
echo "$to is unchanged"
|
||||
rm -f "$target"
|
||||
else
|
||||
echo "updating $to"
|
||||
mv -f "$target" "$realtarget"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# A missing file is only an error for the parser. This is a
|
||||
# blatant hack to let us support using "yacc -d". If -d is not
|
||||
# specified, don't fail when the header file is "missing".
|
||||
if test "$from" = "$parser"; then
|
||||
ret=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Remove the directory.
|
||||
cd ..
|
||||
rm -rf $dirname
|
||||
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
Loading…
Reference in New Issue