Initial commit
This commit is contained in:
commit
1ab1e012c3
340
LICENSE.TXT
Normal file
340
LICENSE.TXT
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
53
Makefile.am
Normal file
53
Makefile.am
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
bin_PROGRAMS = metamath
|
||||||
|
|
||||||
|
noinst_HEADERS = \
|
||||||
|
mmcmdl.h \
|
||||||
|
mmcmds.h \
|
||||||
|
mmdata.h \
|
||||||
|
mmhlpa.h \
|
||||||
|
mmhlpb.h \
|
||||||
|
mminou.h \
|
||||||
|
mmmaci.h \
|
||||||
|
mmpars.h \
|
||||||
|
mmpfas.h \
|
||||||
|
mmunif.h \
|
||||||
|
mmutil.h \
|
||||||
|
mmveri.h \
|
||||||
|
mmvstr.h \
|
||||||
|
mmword.h \
|
||||||
|
mmwtex.h
|
||||||
|
|
||||||
|
metamath_SOURCES = \
|
||||||
|
metamath.c \
|
||||||
|
mmcmdl.c \
|
||||||
|
mmcmds.c \
|
||||||
|
mmdata.c \
|
||||||
|
mmhlpa.c \
|
||||||
|
mmhlpb.c \
|
||||||
|
mminou.c \
|
||||||
|
mmmaci.c \
|
||||||
|
mmpars.c \
|
||||||
|
mmpfas.c \
|
||||||
|
mmunif.c \
|
||||||
|
mmutil.c \
|
||||||
|
mmveri.c \
|
||||||
|
mmvstr.c \
|
||||||
|
mmword.c \
|
||||||
|
mmwtex.c \
|
||||||
|
$(noinst_HEADERS)
|
||||||
|
|
||||||
|
dist_pkgdata_DATA = \
|
||||||
|
big-unifier.mm \
|
||||||
|
demo0.mm \
|
||||||
|
miu.mm \
|
||||||
|
peano.mm \
|
||||||
|
ql.mm \
|
||||||
|
set.mm
|
||||||
|
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
LICENSE.TXT \
|
||||||
|
README.TXT \
|
||||||
|
__README.TXT
|
||||||
|
|
||||||
|
man_MANS = metamath.1
|
155
README.TXT
Normal file
155
README.TXT
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
This package contains the metamath program and several Metamath
|
||||||
|
databases.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
---------
|
||||||
|
|
||||||
|
The metamath program is copyright under the terms of the GNU GPL license
|
||||||
|
version 2 or later. See the file LICENSE.TXT in this directory.
|
||||||
|
|
||||||
|
Individual databases (*.mm files) are either public domain or under
|
||||||
|
the GNU GPL, as indicated by comments in their headers.
|
||||||
|
|
||||||
|
See http://us.metamath.org/copyright.html for further license and
|
||||||
|
copyright information that applies to the content of this package.
|
||||||
|
|
||||||
|
|
||||||
|
Instructions
|
||||||
|
------------
|
||||||
|
|
||||||
|
For Windows, click on "metamath.exe" and type "read set.mm".
|
||||||
|
|
||||||
|
For Unix/Linux/Cygwin/MacOSX using the gcc compiler, compile with the
|
||||||
|
command "gcc m*.c -o metamath", then type "./metamath set.mm" to run.
|
||||||
|
|
||||||
|
As an alternative, if you have autoconf, automake, and a C compiler, you
|
||||||
|
can compile with the command "autoreconf -i && ./configure && make".
|
||||||
|
This "autoconf" approach automatically finds your compiler and its
|
||||||
|
options, and configure takes the usual options (e.g., "--prefix=/usr").
|
||||||
|
The resulting executable will typically be faster because it will check for
|
||||||
|
and enable available optimizations; tests found that the "improve"
|
||||||
|
command ran 28% faster on gcc when using an autoconf-generated "configure".
|
||||||
|
You can again type "./metamath set.mm" to run. After "make" you may
|
||||||
|
install it elsewhere using "sudo make install" (note that this installs
|
||||||
|
".mm" files in the pkgdata directory, by default
|
||||||
|
"/usr/local/share/metamath/"). If you install it this way, you can then
|
||||||
|
run metamath as "metamath /usr/share/metamath/set.mm", copy set.mm
|
||||||
|
locally (cp /usr/share/metamath/set.mm . ; metamath set.mm), or run
|
||||||
|
metamath and type: read "/usr/share/metamath/set.mm" (note that inside
|
||||||
|
metamath, filenames containing "/" must be quoted).
|
||||||
|
|
||||||
|
|
||||||
|
Man page
|
||||||
|
--------
|
||||||
|
|
||||||
|
There is a man page for the Metamath program on Linux systems. It is
|
||||||
|
automatically installed if you use "autoreconf" as described above. To
|
||||||
|
install it manually, copy the file metamath.1 to the appropriate folder,
|
||||||
|
using the command "sudo cp metamath.1 /usr/local/share/man/man1/" and
|
||||||
|
update the man database with the command "sudo mandb". You can then
|
||||||
|
simply type "man metamath" to access the man page.
|
||||||
|
|
||||||
|
|
||||||
|
Optional enhancements
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
For optimized performance under gcc, you can compile as follows:
|
||||||
|
|
||||||
|
gcc m*.c -o metamath -O3 -funroll-loops -finline-functions \
|
||||||
|
-fomit-frame-pointer -Wall -pedantic
|
||||||
|
|
||||||
|
If your compiler supports it, you can also add the option -DINLINE=inline
|
||||||
|
to achieve the 28% performance increase described above.
|
||||||
|
|
||||||
|
|
||||||
|
On Linux/MacOSX/Unix, the Metamath program will be more pleasant to use
|
||||||
|
if you run it inside of rlwrap http://utopia.knoware.nl/~hlub/rlwrap/
|
||||||
|
(checked 3-Jun-2015) which provides up-arrow command history and other
|
||||||
|
command-line editing features. After you install rlwrap per its
|
||||||
|
instructions, invoke the Metamath program with "rlwrap ./metamath
|
||||||
|
set.mm".
|
||||||
|
|
||||||
|
|
||||||
|
In some Linux distributions (such as Debian Woody), if the Backspace
|
||||||
|
key doesn't delete characters typed after the "MM>" prompt, try adding
|
||||||
|
this line to your ~/.bash_profile file:
|
||||||
|
|
||||||
|
stty echoe echok echoctl echoke
|
||||||
|
|
||||||
|
Using rlwrap as described above will also solve this problem.
|
||||||
|
|
||||||
|
|
||||||
|
Additional MacOSX information
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
On MacOSX, select the Terminal application from Applications/Utilities
|
||||||
|
to get to the command line. On recent versions of MacOSX, you need to
|
||||||
|
install gcc separately. Typing "whereis gcc" will return "/usr/bin/gcc"
|
||||||
|
if it is installed. The XCode package is typically used to install it,
|
||||||
|
but it can also be installed without XCode; see
|
||||||
|
|
||||||
|
https://github.com/kennethreitz/osx-gcc-installer/ (checked 15-Feb-2014)
|
||||||
|
|
||||||
|
|
||||||
|
Optional rlwrap user interface enhancement
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
On Linux/MacOSX/Unix, the Metamath program will be more pleasant to use
|
||||||
|
if you run it inside of rlwrap:
|
||||||
|
|
||||||
|
http://utopia.knoware.nl/~hlub/uck/rlwrap/ (checked 15-Feb-2014)
|
||||||
|
|
||||||
|
which provides up-arrow command history and other command-line editing
|
||||||
|
features. After you install rlwrap per its instructions, invoke the
|
||||||
|
Metamath program with "rlwrap ./metamath set.mm".
|
||||||
|
|
||||||
|
(The Windows version of the Metamath program was compiled with lcc,
|
||||||
|
which has similar features built-in.)
|
||||||
|
|
||||||
|
|
||||||
|
Windows Compilation
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
To reproduce the included metamath.exe for Windows, use lcc-win32
|
||||||
|
version 3.8, with the following command:
|
||||||
|
|
||||||
|
lc -O m*.c -o metamath.exe
|
||||||
|
|
||||||
|
|
||||||
|
Further suggestions
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Once in the program, use the "help" command to guide you. For more
|
||||||
|
information, see the Metamath book available at http://metamath.org .
|
||||||
|
|
||||||
|
|
||||||
|
To uninstall
|
||||||
|
------------
|
||||||
|
|
||||||
|
To uninstall, just delete the "metamath" directory - nothing else
|
||||||
|
(Registry, etc.) is touched in your system.
|
||||||
|
|
||||||
|
If you used autoconf's "make install" to install it in system locations,
|
||||||
|
you can use "make uninstall" to remove it.
|
||||||
|
|
||||||
|
|
||||||
|
List of databases
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The data base files included are:
|
||||||
|
|
||||||
|
set.mm - logic and set theory database (see Ch. 3 of the Metamath book).
|
||||||
|
The Metamath Proof Explorer pages were generated from this database.
|
||||||
|
nf.mm - logic and set theory database for Quine's New Foundations set
|
||||||
|
theory.
|
||||||
|
iset.mm - intuitionistic logic and set theory database.
|
||||||
|
hol.mm - higher order logic (simple type theory) database.
|
||||||
|
ql.mm - quantum logic database. The Quantum Logic Explorer pages were
|
||||||
|
generated from this database.
|
||||||
|
demo0.mm - demo of simple formal system (see Ch. 2 of the Metamath book)
|
||||||
|
miu.mm - Hofstadter's MIU-system (see Appendix D of the Metamath book)
|
||||||
|
big-unifier.mm - A unification stress test (see comments in the file).
|
||||||
|
peano.mm - A nicely commented presentation of Peano arithmetic, written
|
||||||
|
by Robert Solovay (unlike the ones above, this database is NOT public
|
||||||
|
domain but is copyright under the terms of the GNU GPL license)
|
155
__README.TXT
Normal file
155
__README.TXT
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
This package contains the metamath program and several Metamath-e
|
||||||
|
databases.-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Copyright-e
|
||||||
|
----------e
|
||||||
|
-e
|
||||||
|
The metamath program is copyright under the terms of the GNU GPL license-e
|
||||||
|
version 2 or later. See the file LICENSE.TXT in this directory.-e
|
||||||
|
-e
|
||||||
|
Individual databases (*.mm files) are either public domain or under-e
|
||||||
|
the GNU GPL, as indicated by comments in their headers.-e
|
||||||
|
-e
|
||||||
|
See http://us.metamath.org/copyright.html for further license and-e
|
||||||
|
copyright information that applies to the content of this package.-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Instructions-e
|
||||||
|
-------------e
|
||||||
|
-e
|
||||||
|
For Windows, click on "metamath.exe" and type "read set.mm".-e
|
||||||
|
-e
|
||||||
|
For Unix/Linux/Cygwin/MacOSX using the gcc compiler, compile with the-e
|
||||||
|
command "gcc m*.c -o metamath", then type "./metamath set.mm" to run.-e
|
||||||
|
-e
|
||||||
|
As an alternative, if you have autoconf, automake, and a C compiler, you-e
|
||||||
|
can compile with the command "autoreconf -i && ./configure && make".-e
|
||||||
|
This "autoconf" approach automatically finds your compiler and its-e
|
||||||
|
options, and configure takes the usual options (e.g., "--prefix=/usr").-e
|
||||||
|
The resulting executable will typically be faster because it will check for-e
|
||||||
|
and enable available optimizations; tests found that the "improve"-e
|
||||||
|
command ran 28% faster on gcc when using an autoconf-generated "configure".-e
|
||||||
|
You can again type "./metamath set.mm" to run. After "make" you may-e
|
||||||
|
install it elsewhere using "sudo make install" (note that this installs-e
|
||||||
|
".mm" files in the pkgdata directory, by default-e
|
||||||
|
"/usr/local/share/metamath/"). If you install it this way, you can then-e
|
||||||
|
run metamath as "metamath /usr/share/metamath/set.mm", copy set.mm-e
|
||||||
|
locally (cp /usr/share/metamath/set.mm . ; metamath set.mm), or run-e
|
||||||
|
metamath and type: read "/usr/share/metamath/set.mm" (note that inside-e
|
||||||
|
metamath, filenames containing "/" must be quoted).-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Man page-e
|
||||||
|
---------e
|
||||||
|
-e
|
||||||
|
There is a man page for the Metamath program on Linux systems. It is-e
|
||||||
|
automatically installed if you use "autoreconf" as described above. To-e
|
||||||
|
install it manually, copy the file metamath.1 to the appropriate folder,-e
|
||||||
|
using the command "sudo cp metamath.1 /usr/local/share/man/man1/" and-e
|
||||||
|
update the man database with the command "sudo mandb". You can then-e
|
||||||
|
simply type "man metamath" to access the man page.-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Optional enhancements-e
|
||||||
|
----------------------e
|
||||||
|
-e
|
||||||
|
For optimized performance under gcc, you can compile as follows:-e
|
||||||
|
-e
|
||||||
|
gcc m*.c -o metamath -O3 -funroll-loops -finline-functions \-e
|
||||||
|
-fomit-frame-pointer -Wall -pedantic-e
|
||||||
|
-e
|
||||||
|
If your compiler supports it, you can also add the option -DINLINE=inline-e
|
||||||
|
to achieve the 28% performance increase described above.-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
On Linux/MacOSX/Unix, the Metamath program will be more pleasant to use-e
|
||||||
|
if you run it inside of rlwrap http://utopia.knoware.nl/~hlub/rlwrap/-e
|
||||||
|
(checked 3-Jun-2015) which provides up-arrow command history and other-e
|
||||||
|
command-line editing features. After you install rlwrap per its-e
|
||||||
|
instructions, invoke the Metamath program with "rlwrap ./metamath-e
|
||||||
|
set.mm".-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
In some Linux distributions (such as Debian Woody), if the Backspace-e
|
||||||
|
key doesn't delete characters typed after the "MM>" prompt, try adding-e
|
||||||
|
this line to your ~/.bash_profile file:-e
|
||||||
|
-e
|
||||||
|
stty echoe echok echoctl echoke-e
|
||||||
|
-e
|
||||||
|
Using rlwrap as described above will also solve this problem.-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Additional MacOSX information-e
|
||||||
|
------------------------------e
|
||||||
|
-e
|
||||||
|
On MacOSX, select the Terminal application from Applications/Utilities-e
|
||||||
|
to get to the command line. On recent versions of MacOSX, you need to-e
|
||||||
|
install gcc separately. Typing "whereis gcc" will return "/usr/bin/gcc"-e
|
||||||
|
if it is installed. The XCode package is typically used to install it,-e
|
||||||
|
but it can also be installed without XCode; see-e
|
||||||
|
-e
|
||||||
|
https://github.com/kennethreitz/osx-gcc-installer/ (checked 15-Feb-2014)-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Optional rlwrap user interface enhancement-e
|
||||||
|
-------------------------------------------e
|
||||||
|
-e
|
||||||
|
On Linux/MacOSX/Unix, the Metamath program will be more pleasant to use-e
|
||||||
|
if you run it inside of rlwrap:-e
|
||||||
|
-e
|
||||||
|
http://utopia.knoware.nl/~hlub/uck/rlwrap/ (checked 15-Feb-2014)-e
|
||||||
|
-e
|
||||||
|
which provides up-arrow command history and other command-line editing-e
|
||||||
|
features. After you install rlwrap per its instructions, invoke the-e
|
||||||
|
Metamath program with "rlwrap ./metamath set.mm".-e
|
||||||
|
-e
|
||||||
|
(The Windows version of the Metamath program was compiled with lcc,-e
|
||||||
|
which has similar features built-in.)-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Windows Compilation-e
|
||||||
|
--------------------e
|
||||||
|
-e
|
||||||
|
To reproduce the included metamath.exe for Windows, use lcc-win32-e
|
||||||
|
version 3.8, with the following command:-e
|
||||||
|
-e
|
||||||
|
lc -O m*.c -o metamath.exe-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
Further suggestions-e
|
||||||
|
--------------------e
|
||||||
|
-e
|
||||||
|
Once in the program, use the "help" command to guide you. For more-e
|
||||||
|
information, see the Metamath book available at http://metamath.org .-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
To uninstall-e
|
||||||
|
-------------e
|
||||||
|
-e
|
||||||
|
To uninstall, just delete the "metamath" directory - nothing else-e
|
||||||
|
(Registry, etc.) is touched in your system.-e
|
||||||
|
-e
|
||||||
|
If you used autoconf's "make install" to install it in system locations,-e
|
||||||
|
you can use "make uninstall" to remove it.-e
|
||||||
|
-e
|
||||||
|
-e
|
||||||
|
List of databases-e
|
||||||
|
------------------e
|
||||||
|
-e
|
||||||
|
The data base files included are:-e
|
||||||
|
-e
|
||||||
|
set.mm - logic and set theory database (see Ch. 3 of the Metamath book).-e
|
||||||
|
The Metamath Proof Explorer pages were generated from this database.-e
|
||||||
|
nf.mm - logic and set theory database for Quine's New Foundations set-e
|
||||||
|
theory.-e
|
||||||
|
iset.mm - intuitionistic logic and set theory database.-e
|
||||||
|
hol.mm - higher order logic (simple type theory) database.-e
|
||||||
|
ql.mm - quantum logic database. The Quantum Logic Explorer pages were-e
|
||||||
|
generated from this database.-e
|
||||||
|
demo0.mm - demo of simple formal system (see Ch. 2 of the Metamath book)-e
|
||||||
|
miu.mm - Hofstadter's MIU-system (see Appendix D of the Metamath book)-e
|
||||||
|
big-unifier.mm - A unification stress test (see comments in the file).-e
|
||||||
|
peano.mm - A nicely commented presentation of Peano arithmetic, written-e
|
||||||
|
by Robert Solovay (unlike the ones above, this database is NOT public-e
|
||||||
|
domain but is copyright under the terms of the GNU GPL license)-e
|
336
big-unifier.mm
Normal file
336
big-unifier.mm
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
$( big-unifier.mm - Version of 30-Aug-2008
|
||||||
|
|
||||||
|
~~ PUBLIC DOMAIN ~~
|
||||||
|
This work is waived of all rights, including copyright, according to the CC0
|
||||||
|
Public Domain Dedication. http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
Norman Megill - http://metamath.org $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
|
||||||
|
This file (big-unifier.mm) is a unification and substitution test for
|
||||||
|
Metamath verifiers, where small input expressions blow up to thousands
|
||||||
|
of symbols. It is a translation of William McCune's "big-unifier.in"
|
||||||
|
for the OTTER theorem prover:
|
||||||
|
|
||||||
|
http://www-unix.mcs.anl.gov/AR/award-2003/big-unifier.in
|
||||||
|
http://www-unix.mcs.anl.gov/AR/award-2003/big-unifier.out
|
||||||
|
|
||||||
|
Description: "Examples of complicated substitutions in condensed
|
||||||
|
detachment. These occur in Larry Wos's proofs that XCB is a single
|
||||||
|
axiom for EC."
|
||||||
|
$)
|
||||||
|
|
||||||
|
|
||||||
|
$c wff |- e ( , ) $.
|
||||||
|
$v x y z w v u v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 $.
|
||||||
|
|
||||||
|
wx $f wff x $. wy $f wff y $. wz $f wff z $. ww $f wff w $.
|
||||||
|
wv $f wff v $. wu $f wff u $. wv1 $f wff v1 $. wv2 $f wff v2 $.
|
||||||
|
wv3 $f wff v3 $. wv4 $f wff v4 $. wv5 $f wff v5 $. wv6 $f wff v6 $.
|
||||||
|
wv7 $f wff v7 $. wv8 $f wff v8 $. wv9 $f wff v9 $. wv10 $f wff v10 $.
|
||||||
|
wv11 $f wff v11 $.
|
||||||
|
|
||||||
|
$( The binary connective of the language "EC". $)
|
||||||
|
wi $a wff e ( x , y ) $.
|
||||||
|
|
||||||
|
${
|
||||||
|
ax-mp.1 $e |- x $.
|
||||||
|
ax-mp.2 $e |- e ( x , y ) $.
|
||||||
|
$( The inference rule. $)
|
||||||
|
ax-mp $a |- y $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( The first axiom. $)
|
||||||
|
ax-maj $a |- e ( e ( e ( e ( e ( x , e ( y , e ( e ( e ( e ( e ( z , e (
|
||||||
|
e ( e ( z , u ) , e ( v , u ) ) , v ) ) , e ( e ( w , e ( e ( e ( w , v6
|
||||||
|
) , e ( v7 , v6 ) ) , v7 ) ) , y ) ) , v8 ) , e ( v9 , v8 ) ) , v9 ) ) )
|
||||||
|
, x ) , v10 ) , e ( v11 , v10 ) ) , v11 ) $.
|
||||||
|
|
||||||
|
$( The second axiom. $)
|
||||||
|
ax-min $a |- e ( e ( e ( e ( e ( e ( x , e ( e ( y , e ( e ( e ( y , z )
|
||||||
|
, e ( u , z ) ) , u ) ) , x ) ) , e ( v , e ( e ( e ( v , w ) , e ( v6 ,
|
||||||
|
w ) ) , v6 ) ) ) , v7 ) , v8 ) , e ( v7 , v8 ) ) , e ( v9 , e ( e ( e (
|
||||||
|
v9 , v10 ) , e ( v11 , v10 ) ) , v11 ) ) ) $.
|
||||||
|
|
||||||
|
$( A 3-step proof that applies ~ ax-mp to the two axioms. The proof was
|
||||||
|
saved in compressed format with "save proof theorem1 /compressed" in
|
||||||
|
the metamath program. $)
|
||||||
|
theorem1 $p |- e ( e ( e ( x , e ( y , e ( e ( e ( y , z ) , e ( u , z ) )
|
||||||
|
, u ) ) ) , v ) , e ( x , v ) ) $=
|
||||||
|
( wi ax-min ax-maj ax-mp ) ABBCFECFFEFFZFZKDFADFFZAFZFJMFFZKNJFFNFZFAO
|
||||||
|
FFZMPAFFZFPFQPFZFLRFFLNKMJAJNQPLAPGPMKBADCEOARLHI $.
|
||||||
|
|
||||||
|
$( This is the same as ~ theorem1 , except that the proof is saved in
|
||||||
|
uncompressed format with "save proof theorem1u /normal" in the metamath
|
||||||
|
program. Note the size difference in the compressed vs. uncompressed
|
||||||
|
proofs. $)
|
||||||
|
theorem1u $p |- e ( e ( e ( x , e ( y , e ( e ( e ( y , z ) , e ( u , z ) )
|
||||||
|
, u ) ) ) , v ) , e ( x , v ) ) $=
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi
|
||||||
|
wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz wi wi wu wi wi wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi
|
||||||
|
wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv
|
||||||
|
wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi
|
||||||
|
wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wi wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wi wi wi wi wx wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi
|
||||||
|
wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi
|
||||||
|
wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi
|
||||||
|
wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wv wi wx wv wi wi wx wi wi wi wi wi wi wi wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wv wi wx wv wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv
|
||||||
|
wi wx wv wi wi wx wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wi wi wi wx wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi
|
||||||
|
wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wi wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi
|
||||||
|
wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi
|
||||||
|
wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi
|
||||||
|
wx wi wi wi wi wi wi wx wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi
|
||||||
|
wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx
|
||||||
|
wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx
|
||||||
|
wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi
|
||||||
|
wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wv wi wx wv wi wi wx wi wi wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wv wi wx wv wi wi wx wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv
|
||||||
|
wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi
|
||||||
|
wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wi wi wi wi wi ax-min wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx
|
||||||
|
wv wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wx wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi
|
||||||
|
wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wv wi wx wv wi wi wx wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wy wx wv wz wu wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi
|
||||||
|
wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wx wx wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx
|
||||||
|
wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wi wv wi wx wv wi wi wx wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx
|
||||||
|
wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi
|
||||||
|
wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi
|
||||||
|
wi wi wx wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi
|
||||||
|
wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi
|
||||||
|
wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu wi wi wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv
|
||||||
|
wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi wi wx wi wi wx wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv
|
||||||
|
wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu
|
||||||
|
wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi
|
||||||
|
wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy
|
||||||
|
wy wz wi wu wz wi wi wu wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz
|
||||||
|
wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv
|
||||||
|
wi wi wx wi wi wi wi wi wx wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy
|
||||||
|
wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi
|
||||||
|
wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi wx wy wy wz wi wu wz
|
||||||
|
wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wy wy wz wi wu wz wi wi wu
|
||||||
|
wi wi wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wx wy wy wz wi wu wz wi
|
||||||
|
wi wu wi wi wi wv wi wx wv wi wi wx wi wi wy wy wz wi wu wz wi wi wu wi wi
|
||||||
|
wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi wx wi wi wi wi wi
|
||||||
|
wi wi wx wy wy wz wi wu wz wi wi wu wi wi wi wv wi wx wv wi wi ax-maj ax-mp
|
||||||
|
$.
|
||||||
|
|
||||||
|
$(
|
||||||
|
|
||||||
|
This comment holds a simple typesetting definition file so that HTML
|
||||||
|
pages can be created with "show statement theorem1/html" in the
|
||||||
|
metamath program.
|
||||||
|
|
||||||
|
$t
|
||||||
|
htmldef "(" as " ( ";
|
||||||
|
htmldef ")" as " ) ";
|
||||||
|
htmldef "e" as " e ";
|
||||||
|
htmldef "wff" as " wff ";
|
||||||
|
htmldef "|-" as " |- ";
|
||||||
|
htmldef "," as " , ";
|
||||||
|
htmldef "x" as " x ";
|
||||||
|
htmldef "y" as " y ";
|
||||||
|
htmldef "z" as " z ";
|
||||||
|
htmldef "w" as " w ";
|
||||||
|
htmldef "v" as " v ";
|
||||||
|
htmldef "u" as " u ";
|
||||||
|
htmldef "v1" as " v1 ";
|
||||||
|
htmldef "v2" as " v2 ";
|
||||||
|
htmldef "v3" as " v3 ";
|
||||||
|
htmldef "v4" as " v4 ";
|
||||||
|
htmldef "v5" as " v5 ";
|
||||||
|
htmldef "v6" as " v6 ";
|
||||||
|
htmldef "v7" as " v7 ";
|
||||||
|
htmldef "v8" as " v8 ";
|
||||||
|
htmldef "v9" as " v9 ";
|
||||||
|
htmldef "v10" as " v10 ";
|
||||||
|
htmldef "v11" as " v11 ";
|
||||||
|
$)
|
86
configure.ac
Normal file
86
configure.ac
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
AC_PREREQ([2.65])
|
||||||
|
AC_INIT([metamath], [0.114], [nm.NOSPAM@alum.mit.edu])
|
||||||
|
AC_CONFIG_SRCDIR([metamath.c])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([foreign])
|
||||||
|
AC_CONFIG_FILES([Makefile])
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
|
# Checks for libraries.
|
||||||
|
|
||||||
|
# Checks for header files.
|
||||||
|
AC_CHECK_HEADERS([limits.h stdlib.h string.h])
|
||||||
|
AC_HEADER_STDBOOL
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
|
AC_FUNC_MALLOC
|
||||||
|
AC_FUNC_REALLOC
|
||||||
|
AC_CHECK_FUNCS([strchr strcspn strstr])
|
||||||
|
|
||||||
|
# Enable gcc warning flags, but only if they seem to work
|
||||||
|
new_CFLAGS="-Wall -Wextra"
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $new_CFLAGS"
|
||||||
|
AC_MSG_CHECKING([[for gcc warning flags]])
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([[
|
||||||
|
#include <stdio.h>
|
||||||
|
int f() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
]])],
|
||||||
|
[AC_MSG_RESULT([yes])],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
AM_CFLAGS="$AM_CFLAGS $new_CFLAGS"])
|
||||||
|
|
||||||
|
# Try to optimize.
|
||||||
|
AC_MSG_CHECKING([[for optimization flags]])
|
||||||
|
new_CFLAGS="-O3 -funroll-loops -finline-functions -fomit-frame-pointer"
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $new_CFLAGS"
|
||||||
|
# Remove any existing "-O2", or it will override what we're doing.
|
||||||
|
CFLAGS=$( printf "%s" "$CFLAGS" | sed -e 's/ -O2/ /' )
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM([[
|
||||||
|
#include <stdio.h>
|
||||||
|
int f() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
]])],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
CFLAGS=$( printf "%s" "$CFLAGS" | sed -e 's/ -O2/ /' )
|
||||||
|
AM_CFLAGS="$AM_CFLAGS $new_CFLAGS"],
|
||||||
|
[AC_MSG_RESULT([no])
|
||||||
|
CFLAGS="$saved_CFLAGS"])
|
||||||
|
|
||||||
|
# Can we use "inline"? We don't use AC_C _INLINE because metamath.c
|
||||||
|
# does not include the autoconf-generated file.
|
||||||
|
AC_MSG_CHECKING([[for 'inline' support]])
|
||||||
|
new_CFLAGS="-DINLINE=inline"
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $new_CFLAGS"
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_SOURCE([[
|
||||||
|
inline int f(void) {}
|
||||||
|
]])],
|
||||||
|
[AC_MSG_RESULT([yes])
|
||||||
|
AM_CFLAGS="$AM_CFLAGS $new_CFLAGS"],
|
||||||
|
[AC_MSG_RESULT([no])])
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
|
||||||
|
echo "CFLAGS=$CFLAGS"
|
||||||
|
AC_SUBST([AM_CFLAGS])
|
||||||
|
AC_SUBST([CFLAGS])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
51
demo0.mm
Normal file
51
demo0.mm
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
$( demo0.mm 1-Jan-04 $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
~~ PUBLIC DOMAIN ~~
|
||||||
|
This work is waived of all rights, including copyright, according to the CC0
|
||||||
|
Public Domain Dedication. http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
Norman Megill - email: nm at alum.mit.edu
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
|
||||||
|
$( This file is the introductory formal system example described
|
||||||
|
in Chapter 2 of the Meamath book. $)
|
||||||
|
|
||||||
|
$( Declare the constant symbols we will use $)
|
||||||
|
$c 0 + = -> ( ) term wff |- $.
|
||||||
|
$( Declare the metavariables we will use $)
|
||||||
|
$v t r s P Q $.
|
||||||
|
$( Specify properties of the metavariables $)
|
||||||
|
tt $f term t $.
|
||||||
|
tr $f term r $.
|
||||||
|
ts $f term s $.
|
||||||
|
wp $f wff P $.
|
||||||
|
wq $f wff Q $.
|
||||||
|
$( Define "term" (part 1) $)
|
||||||
|
tze $a term 0 $.
|
||||||
|
$( Define "term" (part 2) $)
|
||||||
|
tpl $a term ( t + r ) $.
|
||||||
|
$( Define "wff" (part 1) $)
|
||||||
|
weq $a wff t = r $.
|
||||||
|
$( Define "wff" (part 2) $)
|
||||||
|
wim $a wff ( P -> Q ) $.
|
||||||
|
$( State axiom a1 $)
|
||||||
|
a1 $a |- ( t = r -> ( t = s -> r = s ) ) $.
|
||||||
|
$( State axiom a2 $)
|
||||||
|
a2 $a |- ( t + 0 ) = t $.
|
||||||
|
${
|
||||||
|
min $e |- P $.
|
||||||
|
maj $e |- ( P -> Q ) $.
|
||||||
|
$( Define the modus ponens inference rule $)
|
||||||
|
mp $a |- Q $.
|
||||||
|
$}
|
||||||
|
$( Prove a theorem $)
|
||||||
|
th1 $p |- t = t $=
|
||||||
|
$( Here is its proof: $)
|
||||||
|
tt tze tpl tt weq tt tt weq tt a2 tt tze tpl
|
||||||
|
tt weq tt tze tpl tt weq tt tt weq wim tt a2
|
||||||
|
tt tze tpl tt tt a1 mp mp
|
||||||
|
$.
|
||||||
|
|
126
metamath.1
Normal file
126
metamath.1
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
.\" t -*- coding: UTF-8 -*-
|
||||||
|
.\" Man page for metamath
|
||||||
|
.\"
|
||||||
|
.\" Copyright (C) 2018 Aaron Puchert.
|
||||||
|
.\"
|
||||||
|
.\" This program is free software; you can redistribute it and/or modify
|
||||||
|
.\" it under the terms of the GNU General Public License as published by
|
||||||
|
.\" the Free Software Foundation; either version 2 of the License, or
|
||||||
|
.\" (at your option) any later version.
|
||||||
|
.\"
|
||||||
|
.\" This program is distributed in the hope that it will be useful,
|
||||||
|
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
.\" GNU General Public License for more details.
|
||||||
|
.\"
|
||||||
|
.\" You should have received a copy of the GNU General Public License
|
||||||
|
.\" along with this program; if not, write to the Free Software
|
||||||
|
.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
.\"
|
||||||
|
.TH metamath 1 "2018-02-04" Metamath "User Manuals"
|
||||||
|
.SH NAME
|
||||||
|
metamath \- Formal proof verifier and proof assistant
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.BI "metamath [ " "commands" " | " "file" " ]"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B metamath
|
||||||
|
is a formal proof verifier and proof assistant for the Metamath language.
|
||||||
|
It can be initialized via a series of
|
||||||
|
.I commands
|
||||||
|
or with a data base
|
||||||
|
.IR file ,
|
||||||
|
which can then be explored interactively.
|
||||||
|
.PP
|
||||||
|
For details about the Metamath language and the command-line interface, type
|
||||||
|
.B help
|
||||||
|
into the command prompt, or read the Metamath book [1], which should have been
|
||||||
|
installed along with the package.
|
||||||
|
.SH LANGUAGE
|
||||||
|
A Metamath database consists of a sequence of three kinds of tokens
|
||||||
|
separated by white space (which is any sequence of one or more white
|
||||||
|
space characters). The set of keyword tokens is
|
||||||
|
.BR ${ ", " $} ", " $c ", " $v ", " $f ", " $e ", " $d ", " $a ", " $p ", "
|
||||||
|
.BR $. ", " $= ", " $( ", " $) ", " $[ ", and " $] .
|
||||||
|
The latter four are called auxiliary or preprocessing keywords. A
|
||||||
|
.I label
|
||||||
|
token consists of any combination of letters, digits, and the characters hyphen,
|
||||||
|
underscore, and period.
|
||||||
|
The label of an assertion is used to refer to it in a proof.
|
||||||
|
A math
|
||||||
|
.I symbol
|
||||||
|
token may consist of any combination of the 93 printable
|
||||||
|
.BR ascii (7)
|
||||||
|
characters other than
|
||||||
|
.BR $ .
|
||||||
|
All tokens are case-sensitive.
|
||||||
|
.TP
|
||||||
|
.BI $( " comment " $)
|
||||||
|
Comments are ignored.
|
||||||
|
.TP
|
||||||
|
.BI $[ " file " $]
|
||||||
|
Include the contents of a
|
||||||
|
.IR file .
|
||||||
|
.TP
|
||||||
|
.BI ${ " statements " $}
|
||||||
|
Scoped block of statements. A math symbol becomes active when declared and
|
||||||
|
stays active until the end of the block in which it is declared.
|
||||||
|
.TP
|
||||||
|
.BI $v " symbols " $.
|
||||||
|
Declare
|
||||||
|
.I symbols
|
||||||
|
as variables. A variable may not be declared a second time while it is active,
|
||||||
|
but it may be declared again (as a variable, but not as a constant) after it
|
||||||
|
becomes inactive.
|
||||||
|
.TP
|
||||||
|
.BI $c " symbols " $.
|
||||||
|
Declare
|
||||||
|
.I symbols
|
||||||
|
as constants. A constant must be declared in the outermost block and may not be
|
||||||
|
declared a second time.
|
||||||
|
.TP
|
||||||
|
.IB "label " $f " constant variable " $.
|
||||||
|
Variable-type hypothesis to specify the nature or type of a variable (such as
|
||||||
|
`let x be an integer.'). A variable must have its type specified in a
|
||||||
|
.B $f
|
||||||
|
statement before it may be used in a
|
||||||
|
.BR $e ", " $a ", or " $p
|
||||||
|
statement. There may not be two active
|
||||||
|
.B $f
|
||||||
|
statements containing the same variable.
|
||||||
|
.TP
|
||||||
|
.IB "label " $e " constant symbols " $.
|
||||||
|
Logical hypothesis, expressing a logical truth (such as `assume x is prime')
|
||||||
|
that must be established in order for an assertion requiring it to also be true.
|
||||||
|
.TP
|
||||||
|
.BI $d " variables " $.
|
||||||
|
Disjoint variable restriction. For distinct active
|
||||||
|
.IR variables ,
|
||||||
|
it forbids the substitution of one variable with another.
|
||||||
|
.TP
|
||||||
|
.IB "label " $a " constant symbols " $.
|
||||||
|
Axiomatic assertion.
|
||||||
|
.TP
|
||||||
|
.IB "label " $p " constant symbols " $= " proof " $.
|
||||||
|
Provable assertion. The
|
||||||
|
.I proof
|
||||||
|
is a sequence of statement
|
||||||
|
.IR label s.
|
||||||
|
This label sequence serves as a set of instructions that the Metamath program
|
||||||
|
uses to construct a series of math symbol sequences. The construction must
|
||||||
|
ultimately result in the math symbol sequence contained between the
|
||||||
|
.BR $p " and " $=
|
||||||
|
keywords of the
|
||||||
|
.B $p
|
||||||
|
statement. For details, see section 4.3 in [1].
|
||||||
|
Proofs are most easily written using the interactive prompt in
|
||||||
|
.BR metamath .
|
||||||
|
.SH FILES
|
||||||
|
.I /usr/share/metamath
|
||||||
|
.RS
|
||||||
|
Data base files for several formal theories.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.B "[1]"
|
||||||
|
Norman Megill:
|
||||||
|
.UR http://us.metamath.org/downloads/metamath.pdf
|
||||||
|
Metamath, A Computer Language for Pure Mathematics
|
||||||
|
.UE .
|
8102
metamath.c
Normal file
8102
metamath.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
metamath.exe
Executable file
BIN
metamath.exe
Executable file
Binary file not shown.
130
miu.mm
Normal file
130
miu.mm
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
$( miu.mm 20-Oct-2008 $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
|
||||||
|
~~ PUBLIC DOMAIN ~~
|
||||||
|
This work is waived of all rights, including copyright, according to the CC0
|
||||||
|
Public Domain Dedication. http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
Norman Megill - email: nm at alum.mit.edu
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( The MIU-system: A simple formal system $)
|
||||||
|
|
||||||
|
$( Note: This formal system is unusual in that it allows empty wffs.
|
||||||
|
To work with a proof, you must type SET EMPTY_SUBSTITUTION ON before
|
||||||
|
using the PROVE command. By default this is OFF in order to reduce the
|
||||||
|
number of ambiguous unification possibilities that have to be selected
|
||||||
|
during the construction of a proof. $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
Hofstadter's MIU-system is a simple example of a formal
|
||||||
|
system that illustrates some concepts of Metamath. See
|
||||||
|
Douglas R. Hofstadter, "G\"{o}del, Escher, Bach: An Eternal
|
||||||
|
Golden Braid" (Vintage Books, New York, 1979), pp. 33ff. for
|
||||||
|
a description of the MIU-system.
|
||||||
|
|
||||||
|
The system has 3 constant symbols, M, I, and U. The sole
|
||||||
|
axiom of the system is MI. There are 4 rules:
|
||||||
|
Rule I: If you possess a string whose last letter is I,
|
||||||
|
you can add on a U at the end.
|
||||||
|
Rule II: Suppose you have Mx. Then you may add Mxx to
|
||||||
|
your collection.
|
||||||
|
Rule III: If III occurs in one of the strings in your
|
||||||
|
collection, you may make a new string with U in place
|
||||||
|
of III.
|
||||||
|
Rule IV: If UU occurs inside one of your strings, you
|
||||||
|
can drop it.
|
||||||
|
|
||||||
|
Note: The following comment applied to an old version of the Metamath
|
||||||
|
spec that didn't require $f (variable type) hypotheses for variables and
|
||||||
|
is no longer applicable. The current spec was made stricter primarily
|
||||||
|
to reduce the likelihood of inconsistent toy axiom systems, effectively
|
||||||
|
requiring the concept of an "MIU wff" anyway. However, I am keeping the
|
||||||
|
comment for historical reasons, if only to point out an intrinsic
|
||||||
|
difference in Rules III and IV that might have relevance to other proof
|
||||||
|
systems.
|
||||||
|
|
||||||
|
Old comment, obsolete: "Unfortunately, Rules III and IV do not have
|
||||||
|
unique results: strings could have more than one occurrence of III or
|
||||||
|
UU. This requires that we introduce the concept of an "MIU well-formed
|
||||||
|
formula" or wff, which allows us to construct unique symbol sequences to
|
||||||
|
which Rules III and IV can be applied."
|
||||||
|
|
||||||
|
Under the old Metamath spec, the problem this caused was that without
|
||||||
|
the construction of specific wffs to substitute for their variables,
|
||||||
|
Rules III and IV would sometimes not have unique unifications (as
|
||||||
|
required by the spec) during a proof, making proofs more difficult or
|
||||||
|
even impossible.
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( First, we declare the constant symbols of the language.
|
||||||
|
Note that we need two symbols to distinguish the assertion
|
||||||
|
that a sequence is a wff from the assertion that it is a
|
||||||
|
theorem; we have arbitrarily chosen "wff" and "|-". $)
|
||||||
|
$c M I U |- wff $. $( Declare constants $)
|
||||||
|
|
||||||
|
$( Next, we declare some variables. $)
|
||||||
|
$v x y $.
|
||||||
|
|
||||||
|
$( Throughout our theory, we shall assume that these
|
||||||
|
variables represent wffs. $)
|
||||||
|
wx $f wff x $.
|
||||||
|
wy $f wff y $.
|
||||||
|
|
||||||
|
$( Define MIU-wffs. We allow the empty sequence to be a
|
||||||
|
wff. $)
|
||||||
|
|
||||||
|
$( The empty sequence is a wff. $)
|
||||||
|
we $a wff $.
|
||||||
|
$( "M" after any wff is a wff. $)
|
||||||
|
wM $a wff x M $.
|
||||||
|
$( "I" after any wff is a wff. $)
|
||||||
|
wI $a wff x I $.
|
||||||
|
$( "U" after any wff is a wff. $)
|
||||||
|
wU $a wff x U $.
|
||||||
|
$( If "x" and "y" are wffs, so is "x y". This allows the conclusion of
|
||||||
|
` IV ` to be provable as a wff before substitutions into it, for those
|
||||||
|
parsers requiring it. (Added per suggestion of Mel O'Cat 4-Dec-04.) $)
|
||||||
|
wxy $a wff x y $.
|
||||||
|
|
||||||
|
$( Assert the axiom. $)
|
||||||
|
ax $a |- M I $.
|
||||||
|
|
||||||
|
$( Assert the rules. $)
|
||||||
|
${
|
||||||
|
Ia $e |- x I $.
|
||||||
|
$( Given any theorem ending with "I", it remains a theorem
|
||||||
|
if "U" is added after it. (We distinguish the label I_
|
||||||
|
from the math symbol I to conform to the 24-Jun-2006
|
||||||
|
Metamath spec change.) $)
|
||||||
|
I_ $a |- x I U $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
${
|
||||||
|
IIa $e |- M x $.
|
||||||
|
$( Given any theorem starting with "M", it remains a theorem
|
||||||
|
if the part after the "M" is added again after it. $)
|
||||||
|
II $a |- M x x $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
${
|
||||||
|
IIIa $e |- x I I I y $.
|
||||||
|
$( Given any theorem with "III" in the middle, it remains a
|
||||||
|
theorem if the "III" is replace with "U". $)
|
||||||
|
III $a |- x U y $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
${
|
||||||
|
IVa $e |- x U U y $.
|
||||||
|
$( Given any theorem with "UU" in the middle, it remains a
|
||||||
|
theorem if the "UU" is deleted. $)
|
||||||
|
IV $a |- x y $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( Now we prove the theorem MUIIU. You may be interested in
|
||||||
|
comparing this proof with that of Hofstadter (pp. 35 - 36). $)
|
||||||
|
theorem1 $p |- M U I I U $=
|
||||||
|
we wM wU wI we wI wU we wU wI wU we wM we wI wU we wM
|
||||||
|
wI wI wI we wI wI we wI ax II II I_ III II IV $.
|
50
mmcmdl.h
Normal file
50
mmcmdl.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2018 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMCMDL_H_
|
||||||
|
#define METAMATH_MMCMDL_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
flag processCommandLine(void);
|
||||||
|
flag getFullArg(long arg, vstring cmdList);
|
||||||
|
void parseCommandLine(vstring line);
|
||||||
|
flag lastArgMatches(vstring argString);
|
||||||
|
flag cmdMatches(vstring cmdString);
|
||||||
|
long switchPos(vstring swString);
|
||||||
|
void printCommandError(vstring line, long arg, vstring errorMsg);
|
||||||
|
void freeCommandLine(void); /* 4-May-2017 Ari Ferrera */
|
||||||
|
|
||||||
|
#define DEFAULT_COLUMN 16
|
||||||
|
extern pntrString *g_rawArgPntr;
|
||||||
|
extern nmbrString *g_rawArgNmbr;
|
||||||
|
extern long g_rawArgs;
|
||||||
|
extern pntrString *g_fullArg;
|
||||||
|
extern vstring g_fullArgString; /* 1-Nov-2013 nm g_fullArg as one string */
|
||||||
|
extern vstring g_commandPrompt;
|
||||||
|
extern vstring g_commandLine;
|
||||||
|
extern long g_showStatement;
|
||||||
|
extern vstring g_logFileName;
|
||||||
|
extern vstring g_texFileName;
|
||||||
|
extern flag g_PFASmode; /* Proof assistant mode, invoked by PROVE command */
|
||||||
|
/* 15-Aug-2020 nm g_queryMode is global only within mmcmdl.c */
|
||||||
|
/* extern flag g_queryMode; */ /* If 1, explicit questions will be asked even if
|
||||||
|
a field in the input command line is optional */
|
||||||
|
extern flag g_sourceChanged; /* Flag that user made some change to the source
|
||||||
|
file*/
|
||||||
|
extern flag g_proofChanged; /* Flag that user made some change to proof in
|
||||||
|
progress*/
|
||||||
|
extern flag g_commandEcho; /* Echo full command */
|
||||||
|
extern flag g_memoryStatus; /* Always show memory */
|
||||||
|
|
||||||
|
/* 31-Dec-2017 nm */
|
||||||
|
extern flag g_sourceHasBeenRead; /* 1 if a source file has been read in */
|
||||||
|
/* 31-Dec-2017 nm */
|
||||||
|
extern vstring g_rootDirectory; /* Directory to use for included files */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMCMDL_H_ */
|
158
mmcmds.h
Normal file
158
mmcmds.h
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2020 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMCMDS_H_
|
||||||
|
#define METAMATH_MMCMDS_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
/* Type (i.e. print) a statement */
|
||||||
|
void typeStatement(long statemNum,
|
||||||
|
flag briefFlag,
|
||||||
|
flag commentOnlyFlag,
|
||||||
|
flag texFlag,
|
||||||
|
flag htmlFlg);
|
||||||
|
/* Type (i.e. print) a proof */
|
||||||
|
void typeProof(long statemNum,
|
||||||
|
flag pipFlag, /* Type proofInProgress instead of source file proof */
|
||||||
|
long startStep, long endStep,
|
||||||
|
long endIndent,
|
||||||
|
flag essentialFlag,
|
||||||
|
flag renumberFlag,
|
||||||
|
flag unknownFlag,
|
||||||
|
flag notUnifiedFlag,
|
||||||
|
flag reverseFlag,
|
||||||
|
flag noIndentFlag,
|
||||||
|
long startColumn,
|
||||||
|
flag skipRepeatedSteps, /* 28-Jun-2013 nm Added */
|
||||||
|
flag texFlag,
|
||||||
|
flag htmlFlg);
|
||||||
|
/* Show details of step */
|
||||||
|
void showDetailStep(long statemNum, long detailStep);
|
||||||
|
/* Summary of statements in proof */
|
||||||
|
void proofStmtSumm(long statemNum, flag essentialFlag, flag texFlag);
|
||||||
|
/* Traces back the statements used by a proof, recursively. */
|
||||||
|
flag traceProof(long statemNum,
|
||||||
|
flag essentialFlag,
|
||||||
|
flag axiomFlag,
|
||||||
|
vstring matchList, /* 19-May-2013 nm */
|
||||||
|
vstring traceToList, /* 18-Jul-2015 nm */
|
||||||
|
flag testOnlyFlag /* 20-May-2013 nm */);
|
||||||
|
void traceProofWork(long statemNum,
|
||||||
|
flag essentialFlag,
|
||||||
|
vstring traceToList, /* 18-Jul-2015 nm */
|
||||||
|
vstring *statementUsedFlagsP, /* 'y'/'n' flag that statement is used */
|
||||||
|
nmbrString **unprovedListP);
|
||||||
|
/* Traces back the statements used by a proof, recursively, with tree display.*/
|
||||||
|
void traceProofTree(long statemNum,
|
||||||
|
flag essentialFlag, long endIndent);
|
||||||
|
void traceProofTreeRec(long statemNum,
|
||||||
|
flag essentialFlag, long endIndent, long recursDepth);
|
||||||
|
/* Counts the number of steps a completely exploded proof would require */
|
||||||
|
/* (Recursive) */
|
||||||
|
/* 0 is returned if some assertions have incomplete proofs. */
|
||||||
|
double countSteps(long statemNum, flag essentialFlag);
|
||||||
|
/* Traces what statements require the use of a given statement */
|
||||||
|
vstring traceUsage(long statemNum,
|
||||||
|
flag recursiveFlag,
|
||||||
|
long cutoffStmt /* if nonzero, stop scan there */ /* 18-Jul-2015 nm */);
|
||||||
|
vstring htmlDummyVars(long showStmt); /* 12-Aug-2017 nm */
|
||||||
|
vstring htmlAllowedSubst(long showStmt); /* 4-Jan-2014 nm */
|
||||||
|
|
||||||
|
void readInput(void);
|
||||||
|
/* WRITE SOURCE command */
|
||||||
|
void writeSource(/* flag cleanFlag, 3-May-2017 */ /* 1 = "/ CLEAN" qualifier was chosen */
|
||||||
|
flag reformatFlag /* 1 = "/ FORMAT", 2 = "/REWRAP" */,
|
||||||
|
/* 31-Dec-2017 nm */
|
||||||
|
flag splitFlag, /* /SPLIT - write out separate $[ $] includes */
|
||||||
|
flag noVersioningFlag, /* /NO_VERSIONING - no ~1 backup */
|
||||||
|
flag keepSplitsFlag, /* /KEEP_SPLITS - don't delete included files
|
||||||
|
when /SPIT is not specified */
|
||||||
|
vstring extractLabels /* "" means write everything */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* 24-Aug-2020 nm */
|
||||||
|
/* Get info for WRITE SOURCE ... / EXTRACT */
|
||||||
|
void writeExtractedSource(vstring extractLabels, /* EXTRACT argument provided by user */
|
||||||
|
vstring fullOutput_fn, flag noVersioningFlag);
|
||||||
|
|
||||||
|
void fixUndefinedLabels(vstring extractNeeded, vstring *buf);
|
||||||
|
|
||||||
|
void writeDict(void);
|
||||||
|
void eraseSource(void);
|
||||||
|
void verifyProofs(vstring labelMatch, flag verifyFlag);
|
||||||
|
|
||||||
|
|
||||||
|
/* 7-Nov-2015 nm Added this function for date consistency */
|
||||||
|
/* If checkFiles = 0, do not open external files.
|
||||||
|
If checkFiles = 1, check mm*.html, presence of gifs, etc. */
|
||||||
|
void verifyMarkup(vstring labelMatch, flag dateSkip, flag topDateSkip,
|
||||||
|
flag fileSkip,
|
||||||
|
flag underscoreSkip, /* 25-Jun-2020 nm */
|
||||||
|
flag mathboxSkip, /* 17-Jul-2020 nm */
|
||||||
|
flag verboseMode); /* 26-Dec-2016 nm */
|
||||||
|
|
||||||
|
/* 10-Dec-2018 nm Added */
|
||||||
|
void processMarkup(vstring inputFileName, vstring outputFileName,
|
||||||
|
flag processCss, long actionBits);
|
||||||
|
|
||||||
|
/* 3-May-2016 nm */
|
||||||
|
/* List "discouraged" statements with "(Proof modification is discouraged."
|
||||||
|
and "(New usage is discourged.)" comment markup tags. */
|
||||||
|
void showDiscouraged(void);
|
||||||
|
|
||||||
|
/* 14-Sep-2012 nm */
|
||||||
|
/* Take a relative step FIRST, LAST, +nn, -nn (relative to the unknown
|
||||||
|
essential steps) or ALL, and return the actual step for use by ASSIGN,
|
||||||
|
IMPROVE, REPLACE, LET (or 0 in case of ALL, used by IMPROVE). In case
|
||||||
|
stepStr is an unsigned integer nn, it is assumed to already be an actual
|
||||||
|
step and is returned as is. If format is illegal, -1 is returned. */
|
||||||
|
long getStepNum(vstring relStep, /* User's argument */
|
||||||
|
nmbrString *pfInProgress, /* proofInProgress.proof */
|
||||||
|
flag allFlag /* 1 = "ALL" is permissable */);
|
||||||
|
|
||||||
|
/* 22-Apr-2015 nm */
|
||||||
|
/* Convert the actual step numbers of an unassigned step to the relative
|
||||||
|
-1, -2, etc. offset for SHOW NEW_PROOF ... /UNKNOWN, to make it easier
|
||||||
|
for the user to ASSIGN the relative step number. A 0 is returned
|
||||||
|
for the last unknown step. The step numbers of known steps are
|
||||||
|
unchanged. */
|
||||||
|
/* The caller must deallocate the returned nmbrString. */
|
||||||
|
nmbrString *getRelStepNums(nmbrString *pfInProgress);
|
||||||
|
|
||||||
|
/* 19-Sep-2012 nm */
|
||||||
|
/* This procedure finds the next statement number whose label matches
|
||||||
|
stmtName. Wildcards are allowed. If uniqueFlag is 1,
|
||||||
|
there must be exactly one match, otherwise an error message is printed,
|
||||||
|
and -1 is returned. If uniqueFlag is 0, the next match is
|
||||||
|
returned, or -1 if there are no more matches. No error messages are
|
||||||
|
printed when uniqueFlag is 0, except for the special case of
|
||||||
|
startStmt=1. For use by PROVE, REPLACE, ASSIGN. */
|
||||||
|
long getStatementNum(vstring stmtName, /* Possibly with wildcards */
|
||||||
|
long startStmt, /* Starting statement number (1 for full scan) */
|
||||||
|
long maxStmt, /* Must be LESS THAN this statement number */
|
||||||
|
flag aAllowed, /* 1 means $a is allowed */
|
||||||
|
flag pAllowed, /* 1 means $p is allowed */
|
||||||
|
flag eAllowed, /* 1 means $e is allowed */
|
||||||
|
flag fAllowed, /* 1 means $f is allowed */
|
||||||
|
flag efOnlyForMaxStmt, /* If 1, $e and $f must belong to maxStmt */
|
||||||
|
flag uniqueFlag); /* If 1, match must be unique */
|
||||||
|
|
||||||
|
/*extern vstring mainFileName;*/ /* 15-Aug-2020 nm Obsolete on 28-Dec-05 */
|
||||||
|
|
||||||
|
/* For HELP processing */
|
||||||
|
extern flag g_printHelp;
|
||||||
|
void H(vstring helpLine);
|
||||||
|
|
||||||
|
/* For MIDI files - added 8/28/00 */
|
||||||
|
extern flag g_midiFlag; /* Set to 1 if typeProof() is to output MIDI file */
|
||||||
|
extern vstring g_midiParam; /* Parameter string for MIDI file */
|
||||||
|
void outputMidi(long plen, nmbrString *indentationLevels,
|
||||||
|
nmbrString *logicalFlags, vstring g_midiParameter, vstring statementLabel);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMCMDS_H_ */
|
524
mmdata.h
Normal file
524
mmdata.h
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2020 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/* mmdata.h - includes for some principal data structures and data-string
|
||||||
|
handling */
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMDATA_H_
|
||||||
|
#define METAMATH_MMDATA_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
|
||||||
|
/*E*/extern long db,db0,db1,db2,db3,db4,db5,db6,db7,db8,db9;/* debugging flags & variables */
|
||||||
|
typedef char flag; /* A "flag" is simply a character intended for use as a
|
||||||
|
yes/no logical Boolean; 0 = no and 1 = yes */
|
||||||
|
|
||||||
|
extern flag g_listMode; /* 0 = metamath, 1 = list utility */
|
||||||
|
extern flag g_toolsMode; /* In metamath mode: 0 = metamath, 1 = tools */
|
||||||
|
|
||||||
|
typedef long nmbrString; /* String of numbers */
|
||||||
|
typedef void* pntrString; /* String of pointers */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum mTokenType { var_, con_ };
|
||||||
|
#define lb_ '{' /* ${ */
|
||||||
|
#define rb_ '}' /* $} */
|
||||||
|
#define v_ 'v' /* $v */
|
||||||
|
#define c_ 'c' /* $c */
|
||||||
|
#define a_ 'a' /* $a */
|
||||||
|
#define d_ 'd' /* $d */
|
||||||
|
#define e_ 'e' /* $e */
|
||||||
|
#define f_ 'f' /* $f */
|
||||||
|
#define p_ 'p' /* $p */
|
||||||
|
#define eq_ '=' /* $= */
|
||||||
|
#define sc_ '.' /* $. (historically, used to be $; (semicolon) ) */
|
||||||
|
#define illegal_ '?' /* anything else */
|
||||||
|
/* Global variables related to current statement */
|
||||||
|
extern int g_currentScope;
|
||||||
|
/*extern long beginScopeStmtNum;*/ /* 15-Aug-2020 nm changed to local in mmpars.c */
|
||||||
|
|
||||||
|
struct statement_struct { /* Array index is statement number, starting at 1 */
|
||||||
|
long lineNum; /* Line number in file; 0 means not yet determined */
|
||||||
|
vstring fileName; /* File statement is in; "" means not yet determined */
|
||||||
|
vstring labelName; /* Label of statement */
|
||||||
|
flag uniqueLabel; /* Flag that label is unique (future implementations may
|
||||||
|
allow duplicate labels on hypotheses) */
|
||||||
|
char type; /* 2nd character of keyword, e.g. 'e' for $e */
|
||||||
|
int scope; /* Block scope level, increased by ${ and decreased by $};
|
||||||
|
${ has scope _before_ the increase; $} has scope _before_ the decrease */
|
||||||
|
long beginScopeStatementNum; /* statement of previous ${ ; 0 if we're in
|
||||||
|
outermost block */
|
||||||
|
long endScopeStatementNum; /* statement of next $} (populated for opening
|
||||||
|
${ only, 0 otherwise); g_statements+1 if
|
||||||
|
we're in outermost block */ /* 24-Aug-2020 nm */
|
||||||
|
vstring statementPtr; /* Pointer to end of (unmodified) label section used
|
||||||
|
to determine file and line number for error or info messages about
|
||||||
|
the statement */
|
||||||
|
vstring labelSectionPtr; /* Source code before statement keyword
|
||||||
|
- will be updated if labelSection changed */
|
||||||
|
long labelSectionLen;
|
||||||
|
/* 3-May-2017 nm Added labelSectionChanged */
|
||||||
|
char labelSectionChanged; /* Default is 0; if 1, labelSectionPtr points to an
|
||||||
|
allocated vstring that must be freed by ERASE */
|
||||||
|
vstring mathSectionPtr; /* Source code between keyword and $= or $. */
|
||||||
|
long mathSectionLen;
|
||||||
|
/* 3-May-2017 nm Added mathSectionChanged */
|
||||||
|
char mathSectionChanged; /* Default is 0; if 1, mathSectionPtr points to an
|
||||||
|
allocated vstring that must be freed by ERASE */
|
||||||
|
vstring proofSectionPtr; /* Source code between $= and $. */
|
||||||
|
long proofSectionLen;
|
||||||
|
/* 3-May-2017 nm Added proofSectionChanged */
|
||||||
|
char proofSectionChanged; /* Default is 0; if 1, proofSectionPtr points to an
|
||||||
|
allocated vstring that must be freed by ERASE */
|
||||||
|
nmbrString *mathString; /* Parsed mathSection */
|
||||||
|
long mathStringLen;
|
||||||
|
nmbrString *proofString; /* Parsed proofSection (used by $p's only */
|
||||||
|
nmbrString *reqHypList; /* Required hypotheses (excluding $d's) */
|
||||||
|
nmbrString *optHypList; /* Optional hypotheses (excluding $d's) */
|
||||||
|
long numReqHyp; /* Number of required hypotheses */
|
||||||
|
nmbrString *reqVarList; /* Required variables */
|
||||||
|
nmbrString *optVarList; /* Optional variables */
|
||||||
|
nmbrString *reqDisjVarsA; /* Required disjoint variables, 1st of pair */
|
||||||
|
nmbrString *reqDisjVarsB; /* Required disjoint variables, 2nd of pair */
|
||||||
|
nmbrString *reqDisjVarsStmt; /* Req disjoint variables, statem number */
|
||||||
|
nmbrString *optDisjVarsA; /* Optional disjoint variables, 1st of pair */
|
||||||
|
nmbrString *optDisjVarsB; /* Optional disjoint variables, 2nd of pair */
|
||||||
|
nmbrString *optDisjVarsStmt; /* Opt disjoint variables, statem number */
|
||||||
|
long pinkNumber; /* 25-Oct-02 The $a/$p sequence number for web pages */
|
||||||
|
/* 18-Dec-2016 nm */
|
||||||
|
long headerStartStmt; /* # of stmt following previous $a, $p */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sort keys for statement labels (allocated by parseLabels) */
|
||||||
|
extern long *g_labelKey;
|
||||||
|
|
||||||
|
struct includeCall_struct {
|
||||||
|
/* This structure holds all information related to $[ $] (include) statements
|
||||||
|
in the input source files, for error message processing. */
|
||||||
|
vstring source_fn; /* Name of the file where the
|
||||||
|
inclusion source is located (= parent file for $( Begin $[... etc.) */
|
||||||
|
vstring included_fn; /* Name of the file in the
|
||||||
|
inclusion statement e.g. "$( Begin $[ included_fn..." */
|
||||||
|
long current_offset; /* This is the starting
|
||||||
|
character position of the included file w.r.t entire source buffer */
|
||||||
|
long current_line; /* The line number
|
||||||
|
of the start of the included file (=1) or the continuation line of
|
||||||
|
the parent file */
|
||||||
|
flag pushOrPop; /* 0 means included file, 1 means continuation of parent */
|
||||||
|
vstring current_includeSource; /* (Currently) assigned
|
||||||
|
only if we may need it for a later Begin comparison */
|
||||||
|
long current_includeLength; /* Length of the file
|
||||||
|
to be included (0 if the file was previously included) */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mathToken_struct {
|
||||||
|
vstring tokenName; /* may be used more than once at different scopes */
|
||||||
|
long length; /* to speed up parsing scans */
|
||||||
|
char tokenType; /* variable or constant - (char)var_ or (char)con_ */
|
||||||
|
flag active; /* 1 if token is recognized in current scope */
|
||||||
|
int scope; /* scope level token was declared at */
|
||||||
|
long tmp; /* Temporary field use to speed up certain functions */
|
||||||
|
long statement; /* Statement declared in */
|
||||||
|
long endStatement; /* Statement of end of scope it was declared in */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sort keys for math tokens (allocated by parseMathDecl) */
|
||||||
|
extern long *g_mathKey;
|
||||||
|
|
||||||
|
extern long g_MAX_STATEMENTS;
|
||||||
|
extern long g_MAX_MATHTOKENS;
|
||||||
|
extern struct statement_struct *g_Statement;
|
||||||
|
/*Obs*/ /*extern struct label_struct *label;*/
|
||||||
|
|
||||||
|
/* Warning: mathToken[i] is 0-based, not 1-based! */
|
||||||
|
extern struct mathToken_struct *g_MathToken;
|
||||||
|
extern long g_statements, /*labels,*/ g_mathTokens;
|
||||||
|
/*extern long maxMathTokenLength;*/ /* 15-Aug-2020 nm Not used */
|
||||||
|
|
||||||
|
extern long g_MAX_INCLUDECALLS;
|
||||||
|
extern struct includeCall_struct *g_IncludeCall;
|
||||||
|
extern long g_includeCalls;
|
||||||
|
|
||||||
|
extern char *g_sourcePtr; /* Pointer to buffer in memory with input source */
|
||||||
|
extern long g_sourceLen; /* Number of chars. in all inputs files combined (after includes)*/
|
||||||
|
|
||||||
|
/* 4-May-2016 nm */
|
||||||
|
/* For use by getMarkupFlag() */
|
||||||
|
#define PROOF_DISCOURAGED_MARKUP "(Proof modification is discouraged.)"
|
||||||
|
#define USAGE_DISCOURAGED_MARKUP "(New usage is discouraged.)"
|
||||||
|
/* Mode argument for getMarkupFlag() */
|
||||||
|
#define PROOF_DISCOURAGED 1
|
||||||
|
#define USAGE_DISCOURAGED 2
|
||||||
|
#define RESET 0
|
||||||
|
/* Mode argument for getContrib() */
|
||||||
|
#define GC_RESET 0
|
||||||
|
#define GC_RESET_STMT 10
|
||||||
|
#define CONTRIBUTOR 1
|
||||||
|
#define CONTRIB_DATE 2
|
||||||
|
#define REVISER 3
|
||||||
|
#define REVISE_DATE 4
|
||||||
|
#define SHORTENER 5
|
||||||
|
#define SHORTEN_DATE 6
|
||||||
|
#define MOST_RECENT_DATE 7
|
||||||
|
#define GC_ERROR_CHECK_SILENT 8
|
||||||
|
#define GC_ERROR_CHECK_PRINT 9
|
||||||
|
|
||||||
|
/* 12-May-2017 nm */
|
||||||
|
/* DATE_BELOW_PROOF, if defined, causes generation and error-checking of
|
||||||
|
the date below the proof (which some day will be obsolete). Comment
|
||||||
|
it out when this checking is no longer needed. */
|
||||||
|
/*#define DATE_BELOW_PROOF*/
|
||||||
|
|
||||||
|
/* 14-May-2017 nm */
|
||||||
|
/* TODO: someday we should create structures to hold global vars, and
|
||||||
|
clear their string components in eraseSource() */
|
||||||
|
extern vstring g_contributorName;
|
||||||
|
#define DEFAULT_CONTRIBUTOR "?who?"
|
||||||
|
|
||||||
|
extern vstring g_proofDiscouragedMarkup;
|
||||||
|
extern vstring g_usageDiscouragedMarkup;
|
||||||
|
extern flag g_globalDiscouragement; /* SET DISCOURAGEMENT */
|
||||||
|
|
||||||
|
/* Allocation and deallocation in memory pool */
|
||||||
|
void *poolFixedMalloc(long size /* bytes */);
|
||||||
|
void *poolMalloc(long size /* bytes */);
|
||||||
|
void poolFree(void *ptr);
|
||||||
|
void addToUsedPool(void *ptr);
|
||||||
|
/* Purges reset memory pool usage */
|
||||||
|
void memFreePoolPurge(flag untilOK);
|
||||||
|
/* Statistics */
|
||||||
|
void getPoolStats(long *freeAlloc, long *usedAlloc, long *usedActual);
|
||||||
|
|
||||||
|
/* Initial memory allocation */
|
||||||
|
void initBigArrays(void);
|
||||||
|
|
||||||
|
/* Find the number of free memory bytes */
|
||||||
|
long getFreeSpace(long max);
|
||||||
|
|
||||||
|
/* Fatal memory allocation error */
|
||||||
|
void outOfMemory(vstring msg);
|
||||||
|
|
||||||
|
/* Bug check error */
|
||||||
|
void bug(int bugNum);
|
||||||
|
|
||||||
|
|
||||||
|
/* Null nmbrString -- -1 flags the end of a nmbrString */
|
||||||
|
struct nullNmbrStruct {
|
||||||
|
long poolLoc;
|
||||||
|
long allocSize;
|
||||||
|
long actualSize;
|
||||||
|
nmbrString nullElement; };
|
||||||
|
extern struct nullNmbrStruct g_NmbrNull;
|
||||||
|
#define NULL_NMBRSTRING &(g_NmbrNull.nullElement)
|
||||||
|
|
||||||
|
/* Null pntrString -- NULL flags the end of a pntrString */
|
||||||
|
struct nullPntrStruct {
|
||||||
|
long poolLoc;
|
||||||
|
long allocSize;
|
||||||
|
long actualSize;
|
||||||
|
pntrString nullElement; };
|
||||||
|
extern struct nullPntrStruct g_PntrNull;
|
||||||
|
#define NULL_PNTRSTRING &(g_PntrNull.nullElement)
|
||||||
|
|
||||||
|
|
||||||
|
/* 26-Apr-2008 nm Added */
|
||||||
|
/* This function returns a 1 if any entry in a comma-separated list
|
||||||
|
matches using the matches() function. */
|
||||||
|
flag matchesList(vstring testString, vstring pattern, char wildCard,
|
||||||
|
char oneCharWildCard);
|
||||||
|
|
||||||
|
/* This function returns a 1 if the first argument matches the pattern of
|
||||||
|
the second argument. The second argument may have 0-or-more and
|
||||||
|
exactly-1 character match wildcards, typically '*' and '?'.*/
|
||||||
|
/* 30-Jan-06 nm Added single-character-match argument */
|
||||||
|
flag matches(vstring testString, vstring pattern, char wildCard,
|
||||||
|
char oneCharWildCard);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*********** Number string functions *******************************/
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
/******* Special pupose routines for better
|
||||||
|
memory allocation (use with caution) *******/
|
||||||
|
|
||||||
|
extern long g_nmbrTempAllocStackTop; /* Top of stack for nmbrTempAlloc funct */
|
||||||
|
extern long g_nmbrStartTempAllocStack; /* Where to start freeing temporary
|
||||||
|
allocation when nmbrLet() is called (normally 0, except for nested
|
||||||
|
nmbrString functions) */
|
||||||
|
|
||||||
|
/* Make string have temporary allocation to be released by next nmbrLet() */
|
||||||
|
/* Warning: after nmbrMakeTempAlloc() is called, the nmbrString may NOT be
|
||||||
|
assigned again with nmbrLet() */
|
||||||
|
void nmbrMakeTempAlloc(nmbrString *s);
|
||||||
|
/* Make string have temporary allocation to be
|
||||||
|
released by next nmbrLet() */
|
||||||
|
|
||||||
|
/**************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* String assignment - MUST be used to assign vstrings */
|
||||||
|
void nmbrLet(nmbrString **target,nmbrString *source);
|
||||||
|
|
||||||
|
/* String concatenation - last argument MUST be NULL */
|
||||||
|
nmbrString *nmbrCat(nmbrString *string1,...);
|
||||||
|
|
||||||
|
/* Emulation of nmbrString functions similar to BASIC string functions */
|
||||||
|
nmbrString *nmbrSeg(nmbrString *sin, long p1, long p2);
|
||||||
|
nmbrString *nmbrMid(nmbrString *sin, long p, long l);
|
||||||
|
nmbrString *nmbrLeft(nmbrString *sin, long n);
|
||||||
|
nmbrString *nmbrRight(nmbrString *sin, long n);
|
||||||
|
|
||||||
|
/* Allocate and return an "empty" string n "characters" long */
|
||||||
|
nmbrString *nmbrSpace(long n);
|
||||||
|
|
||||||
|
long nmbrLen(nmbrString *s);
|
||||||
|
long nmbrAllocLen(nmbrString *s);
|
||||||
|
void nmbrZapLen(nmbrString *s, long length);
|
||||||
|
|
||||||
|
/* Search for string2 in string 1 starting at start_position */
|
||||||
|
long nmbrInstr(long start, nmbrString *sin, nmbrString *s);
|
||||||
|
|
||||||
|
/* Search for string2 in string 1 in reverse starting at start_position */
|
||||||
|
/* (Reverse nmbrInstr) */
|
||||||
|
long nmbrRevInstr(long start_position,nmbrString *string1,
|
||||||
|
nmbrString *string2);
|
||||||
|
|
||||||
|
/* 1 if strings are equal, 0 otherwise */
|
||||||
|
int nmbrEq(nmbrString *sout,nmbrString *sin);
|
||||||
|
|
||||||
|
/* Converts mString to a vstring with one space between tokens */
|
||||||
|
vstring nmbrCvtMToVString(nmbrString *s);
|
||||||
|
|
||||||
|
/* Converts rString to a vstring with one space between tokens */
|
||||||
|
/* 25-Jan-2016 nm Added explicitFormat, statemNum */
|
||||||
|
vstring nmbrCvtRToVString(nmbrString *s,
|
||||||
|
flag explicitTargets, /* 25-Jan-2016 */
|
||||||
|
long statemNum); /* 25-Jan-2016 */
|
||||||
|
|
||||||
|
/* Get step numbers in an rString - needed by cvtRToVString & elsewhere */
|
||||||
|
nmbrString *nmbrGetProofStepNumbs(nmbrString *reason);
|
||||||
|
|
||||||
|
/* Converts any nmbrString to an ASCII string of numbers corresponding
|
||||||
|
to the .tokenNum field -- used for debugging only. */
|
||||||
|
vstring nmbrCvtAnyToVString(nmbrString *s);
|
||||||
|
|
||||||
|
/* Extract variables from a math token string */
|
||||||
|
nmbrString *nmbrExtractVars(nmbrString *m);
|
||||||
|
|
||||||
|
/* Determine if an element is in a nmbrString; return position if it is */
|
||||||
|
long nmbrElementIn(long start, nmbrString *g, long element);
|
||||||
|
|
||||||
|
/* Add a single number to end of a nmbrString - faster than nmbrCat */
|
||||||
|
nmbrString *nmbrAddElement(nmbrString *g, long element);
|
||||||
|
|
||||||
|
/* Get the set union of two math token strings (presumably
|
||||||
|
variable lists) */
|
||||||
|
nmbrString *nmbrUnion(nmbrString *m1,nmbrString *m2);
|
||||||
|
|
||||||
|
/* Get the set intersection of two math token strings (presumably
|
||||||
|
variable lists) */
|
||||||
|
nmbrString *nmbrIntersection(nmbrString *m1,nmbrString *m2);
|
||||||
|
|
||||||
|
/* Get the set difference m1-m2 of two math token strings (presumably
|
||||||
|
variable lists) */
|
||||||
|
nmbrString *nmbrSetMinus(nmbrString *m1,nmbrString *m2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This is a utility function that returns the length of a subproof that
|
||||||
|
ends at step */
|
||||||
|
long nmbrGetSubproofLen(nmbrString *proof, long step);
|
||||||
|
|
||||||
|
/* This function returns a "squished" proof, putting in {} references
|
||||||
|
to previous subproofs. */
|
||||||
|
nmbrString *nmbrSquishProof(nmbrString *proof);
|
||||||
|
|
||||||
|
/* This function unsquishes a "squished" proof, replacing {} references
|
||||||
|
to previous subproofs by the subproofs themselvs. The returned nmbrString
|
||||||
|
must be deallocated by the caller. */
|
||||||
|
nmbrString *nmbrUnsquishProof(nmbrString *proof);
|
||||||
|
|
||||||
|
/* This function returns the indentation level vs. step number of a proof
|
||||||
|
string. This information is used for formatting proof displays. The
|
||||||
|
function calls itself recursively, but the first call should be with
|
||||||
|
startingLevel = 0. The caller is responsible for deallocating the
|
||||||
|
result. */
|
||||||
|
nmbrString *nmbrGetIndentation(nmbrString *proof,
|
||||||
|
long startingLevel);
|
||||||
|
|
||||||
|
/* This function returns essential (1) or floating (0) vs. step number of a
|
||||||
|
proof string. This information is used for formatting proof displays. The
|
||||||
|
function calls itself recursively, but the first call should be with
|
||||||
|
startingLevel = 0. The caller is responsible for deallocating the
|
||||||
|
result. */
|
||||||
|
nmbrString *nmbrGetEssential(nmbrString *proof);
|
||||||
|
|
||||||
|
/* This function returns the target hypothesis vs. step number of a proof
|
||||||
|
string. This information is used for formatting proof displays. The
|
||||||
|
function calls itself recursively. The caller is responsible for
|
||||||
|
deallocating the result. statemNum is the statement being proved. */
|
||||||
|
nmbrString *nmbrGetTargetHyp(nmbrString *proof, long statemNum);
|
||||||
|
|
||||||
|
/* Converts a proof string to a compressed-proof-format ASCII string.
|
||||||
|
Normally, the proof string would be compacted with squishProof first,
|
||||||
|
although it's not a requirement. */
|
||||||
|
/* The statement number is needed because required hypotheses are
|
||||||
|
implicit in the compressed proof. */
|
||||||
|
vstring compressProof(nmbrString *proof, long statemNum,
|
||||||
|
flag oldCompressionAlgorithm);
|
||||||
|
|
||||||
|
/* Gets length of the ASCII form of a compressed proof */
|
||||||
|
long compressedProofSize(nmbrString *proof, long statemNum);
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*********** Pointer string functions ******************************/
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
/******* Special pupose routines for better
|
||||||
|
memory allocation (use with caution) *******/
|
||||||
|
|
||||||
|
extern long g_pntrTempAllocStackTop; /* Top of stack for pntrTempAlloc funct */
|
||||||
|
extern long g_pntrStartTempAllocStack; /* Where to start freeing temporary
|
||||||
|
allocation when pntrLet() is called (normally 0, except for nested
|
||||||
|
pntrString functions) */
|
||||||
|
|
||||||
|
/* Make string have temporary allocation to be released by next pntrLet() */
|
||||||
|
/* Warning: after pntrMakeTempAlloc() is called, the pntrString may NOT be
|
||||||
|
assigned again with pntrLet() */
|
||||||
|
void pntrMakeTempAlloc(pntrString *s);
|
||||||
|
/* Make string have temporary allocation to be
|
||||||
|
released by next pntrLet() */
|
||||||
|
|
||||||
|
/**************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* String assignment - MUST be used to assign vstrings */
|
||||||
|
void pntrLet(pntrString **target,pntrString *source);
|
||||||
|
|
||||||
|
/* String concatenation - last argument MUST be NULL */
|
||||||
|
pntrString *pntrCat(pntrString *string1,...);
|
||||||
|
|
||||||
|
/* Emulation of pntrString functions similar to BASIC string functions */
|
||||||
|
pntrString *pntrSeg(pntrString *sin, long p1, long p2);
|
||||||
|
pntrString *pntrMid(pntrString *sin, long p, long length);
|
||||||
|
pntrString *pntrLeft(pntrString *sin, long n);
|
||||||
|
pntrString *pntrRight(pntrString *sin, long n);
|
||||||
|
|
||||||
|
/* Allocate and return an "empty" string n "characters" long */
|
||||||
|
pntrString *pntrSpace(long n);
|
||||||
|
|
||||||
|
/* Allocate and return an "empty" string n "characters" long
|
||||||
|
initialized to nmbrStrings instead of vStrings */
|
||||||
|
pntrString *pntrNSpace(long n);
|
||||||
|
|
||||||
|
/* Allocate and return an "empty" string n "characters" long
|
||||||
|
initialized to pntrStrings instead of vStrings */
|
||||||
|
pntrString *pntrPSpace(long n);
|
||||||
|
|
||||||
|
long pntrLen(pntrString *s);
|
||||||
|
long pntrAllocLen(pntrString *s);
|
||||||
|
void pntrZapLen(pntrString *s, long length);
|
||||||
|
|
||||||
|
/* Search for string2 in string 1 starting at start_position */
|
||||||
|
long pntrInstr(long start, pntrString *sin, pntrString *s);
|
||||||
|
|
||||||
|
/* Search for string2 in string 1 in reverse starting at start_position */
|
||||||
|
/* (Reverse pntrInstr) */
|
||||||
|
long pntrRevInstr(long start_position,pntrString *string1,
|
||||||
|
pntrString *string2);
|
||||||
|
|
||||||
|
/* 1 if strings are equal, 0 otherwise */
|
||||||
|
int pntrEq(pntrString *sout,pntrString *sin);
|
||||||
|
|
||||||
|
/* Add a single null string element to a pntrString - faster than pntrCat */
|
||||||
|
pntrString *pntrAddElement(pntrString *g);
|
||||||
|
|
||||||
|
/* Add a single null pntrString element to a pntrString - faster than pntrCat */
|
||||||
|
pntrString *pntrAddGElement(pntrString *g);
|
||||||
|
|
||||||
|
/* Utility functions */
|
||||||
|
|
||||||
|
/* 0/1 knapsack algorithm */
|
||||||
|
long knapsack01(long items, long *size, long *worth, long maxSize,
|
||||||
|
char *itemIncluded /* output: 1 = item included, 0 = not included */);
|
||||||
|
|
||||||
|
/* 2D matrix allocation and deallocation */
|
||||||
|
long **alloc2DMatrix(size_t xsize, size_t ysize);
|
||||||
|
void free2DMatrix(long **matrix, size_t xsize /*, size_t ysize*/);
|
||||||
|
|
||||||
|
/* Returns the amount of indentation of a statement label. Used to
|
||||||
|
determine how much to indent a saved proof. */
|
||||||
|
long getSourceIndentation(long statemNum);
|
||||||
|
|
||||||
|
/* Returns any comment (description) that occurs just before a statement */
|
||||||
|
vstring getDescription(long statemNum);
|
||||||
|
|
||||||
|
/* Returns the label section of a statement with all comments except the
|
||||||
|
last removed. */
|
||||||
|
vstring getDescriptionAndLabel(long statemNum);
|
||||||
|
|
||||||
|
/* Reconstruct the full header from the strings returned by
|
||||||
|
getSectionHeadings() */
|
||||||
|
/*** deleted 12-Sep-2020
|
||||||
|
vstring buildHeader(vstring header, vstring hdrComment, vstring decoration);
|
||||||
|
***/
|
||||||
|
|
||||||
|
/* Returns 1 if comment has an "is discouraged" markup tag */
|
||||||
|
flag getMarkupFlag(long statemNum, char mode);
|
||||||
|
|
||||||
|
/***** deleted 3-May-2017
|
||||||
|
/@ Extract any contributors and dates from statement description.
|
||||||
|
If missing, the corresponding return strings are blank. @/
|
||||||
|
flag getContrib(long stmtNum,
|
||||||
|
vstring @contributor, vstring @contribDate,
|
||||||
|
vstring @revisor, vstring @reviseDate,
|
||||||
|
vstring @shortener, vstring @shortenDate,
|
||||||
|
vstring @mostRecentDate,
|
||||||
|
flag printErrorsFlag,
|
||||||
|
flag mode /@ 0 == RESET = reset, 1 = normal @/);
|
||||||
|
************/
|
||||||
|
|
||||||
|
/* Extract any contributors and dates from statement description.
|
||||||
|
If missing, the corresponding return string is blank.
|
||||||
|
See GC_RESET etc. modes above. Caller must deallocate returned
|
||||||
|
string. */
|
||||||
|
vstring getContrib(long stmtNum, char mode);
|
||||||
|
|
||||||
|
|
||||||
|
/*#ifdef DATE_BELOW_PROOF*/ /* 12-May-2017 nm */
|
||||||
|
/* 14-May-2017 nm - re-enabled for purpose of converting old .mm's */
|
||||||
|
/* Extract up to 2 dates after a statement's proof. If no date is present,
|
||||||
|
date1 will be blank. If no 2nd date is present, date2 will be blank. */
|
||||||
|
void getProofDate(long stmtNum, vstring *date1, vstring *date2);
|
||||||
|
/*#endif*/
|
||||||
|
|
||||||
|
/* Get date, month, year fields from a dd-mmm-yyyy date string,
|
||||||
|
where dd may be 1 or 2 digits, mmm is 1st 3 letters of month,
|
||||||
|
and yyyy is 2 or 4 digits. A 1 is returned if an error was detected. */
|
||||||
|
flag parseDate(vstring dateStr, long *dd, long *mmm, long *yyyy);
|
||||||
|
|
||||||
|
/* Build date from numeric fields. mmm should be a number from 1 to 12. */
|
||||||
|
void buildDate(long dd, long mmm, long yyyy, vstring *dateStr);
|
||||||
|
|
||||||
|
/* Compare two dates in the form dd-mmm-yyyy. -1 = date1 < date2,
|
||||||
|
0 = date1 = date2, 1 = date1 > date2. There is no error checking. */
|
||||||
|
flag compareDates(vstring date1, vstring date2);
|
||||||
|
|
||||||
|
/* 17-Nov-2015 nm */
|
||||||
|
extern vstring g_qsortKey;
|
||||||
|
/* Used by qsortStringCmp; pointer only, do not deallocate */
|
||||||
|
/* Comparison function for qsort */
|
||||||
|
int qsortStringCmp(const void *p1, const void *p2);
|
||||||
|
|
||||||
|
/* 4-May-2017 Ari Ferrera */
|
||||||
|
/* Call on exit to free memory */
|
||||||
|
void freeData(void);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMDATA_H_ */
|
15
mmhlpa.h
Normal file
15
mmhlpa.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2005 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMHLPA_H_
|
||||||
|
#define METAMATH_MMHLPA_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
|
||||||
|
void help0(vstring helpCmd);
|
||||||
|
void help1(vstring helpCmd);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMHLPA_H_ */
|
15
mmhlpb.h
Normal file
15
mmhlpb.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2015 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMHLPB_H_
|
||||||
|
#define METAMATH_MMHLPB_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
|
||||||
|
void help2(vstring helpCmd);
|
||||||
|
void help3(vstring helpCmd);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMHLPB_H_ */
|
96
mminou.h
Normal file
96
mminou.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2020 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMINOU_H_
|
||||||
|
#define METAMATH_MMINOU_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
extern int g_errorCount; /* Total error count */
|
||||||
|
|
||||||
|
/* Global variables used by print2() */
|
||||||
|
extern flag g_logFileOpenFlag;
|
||||||
|
extern FILE *g_logFilePtr;
|
||||||
|
extern FILE *g_listFile_fp;
|
||||||
|
/* Global variables used by print2() */
|
||||||
|
extern flag g_outputToString;
|
||||||
|
extern vstring g_printString;
|
||||||
|
/* Global variables used by cmdInput() */
|
||||||
|
#define MAX_COMMAND_FILE_NESTING 10
|
||||||
|
extern long g_commandFileNestingLevel;
|
||||||
|
extern FILE *g_commandFilePtr[MAX_COMMAND_FILE_NESTING + 1];
|
||||||
|
extern vstring g_commandFileName[MAX_COMMAND_FILE_NESTING + 1];
|
||||||
|
extern flag g_commandFileSilent[MAX_COMMAND_FILE_NESTING + 1];
|
||||||
|
extern flag g_commandFileSilentFlag;
|
||||||
|
/* 23-Oct-2006 nm For SUBMIT ... /SILENT */
|
||||||
|
|
||||||
|
extern FILE /* *inputDef_fp,*/ *g_input_fp /*,*g_output_fp*/; /* File pointers */
|
||||||
|
/* 31-Dec-2017 nm g_output_fp deleted */
|
||||||
|
extern vstring /* inputDef_fn,*/ g_input_fn, g_output_fn; /* File names */
|
||||||
|
|
||||||
|
/* 19-Jun-2020 nm No longer needed since printBuffer is now dynamically
|
||||||
|
allocated. */
|
||||||
|
/*****************************
|
||||||
|
/@ PRINTBUFFERSIZE should be at least as long as the longest string we
|
||||||
|
expect (an unfortunate, dangerous limitation of C?) - although if >79
|
||||||
|
chars are output on a line bug #1505 warning will occur @/
|
||||||
|
#define PRINTBUFFERSIZE 10001
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
/* Warning: never call print2 with string longer than PRINTBUFFERSIZE - 1 */
|
||||||
|
/* print2 returns 0 if the user has quit the printout. */
|
||||||
|
flag print2(char* fmt,...);
|
||||||
|
extern long g_screenHeight; /* Height of screen */ /* 18-Nov-05 nm Added */
|
||||||
|
extern long g_screenWidth; /* Width of screen */
|
||||||
|
#define MAX_LEN 79 /* Default width of screen */
|
||||||
|
#define SCREEN_HEIGHT 23 /* Lines on screen, minus 1 to account for prompt */
|
||||||
|
extern flag g_scrollMode; /* Flag for continuous or prompted scroll */
|
||||||
|
extern flag g_quitPrint; /* Flag that user typed 'q' to last scrolling prompt */
|
||||||
|
|
||||||
|
/* printLongLine automatically puts a newline \n in the output line. */
|
||||||
|
void printLongLine(vstring line, vstring startNextLine, vstring breakMatch);
|
||||||
|
vstring cmdInput(FILE *stream,vstring ask);
|
||||||
|
vstring cmdInput1(vstring ask);
|
||||||
|
|
||||||
|
enum severity {notice_,warning_,error_,fatal_};
|
||||||
|
void errorMessage(vstring line, long lineNum, long column, long tokenLength,
|
||||||
|
vstring error, vstring fileName, long statementNum, flag warnFlag);
|
||||||
|
|
||||||
|
/* Opens files with error message; opens output files with
|
||||||
|
backup of previous version. Mode must be "r" or "w". */
|
||||||
|
FILE *fSafeOpen(vstring fileName, vstring mode, flag noVersioningFlag);
|
||||||
|
|
||||||
|
/* Renames a file with backup of previous version. If non-zero
|
||||||
|
is returned, there was an error. */
|
||||||
|
int fSafeRename(vstring oldFileName, vstring newFileName);
|
||||||
|
|
||||||
|
/* Finds the name of the first file of the form filePrefix +
|
||||||
|
nnn + ".tmp" that does not exist. THE CALLER MUST DEALLOCATE
|
||||||
|
THE RETURNED STRING. */
|
||||||
|
vstring fGetTmpName(vstring filePrefix);
|
||||||
|
|
||||||
|
/* This function returns a character string containing the entire contents of
|
||||||
|
an ASCII file, or Unicode file with only ASCII characters. On some
|
||||||
|
systems it is faster than reading the file line by line. THE CALLER
|
||||||
|
MUST DEALLOCATE THE RETURNED STRING. If a NULL is returned, the file
|
||||||
|
could not be opened or had a non-ASCII Unicode character or some other
|
||||||
|
problem. If verbose is 0, error and warning messages are suppressed. */
|
||||||
|
/* 31-Dec-2017 nm Add charCount return argument */
|
||||||
|
vstring readFileToString(vstring fileName, char verbose, long *charCount);
|
||||||
|
|
||||||
|
/* 16-Aug-2016 nm */
|
||||||
|
/* Returns total elapsed time in seconds since starting session (for the
|
||||||
|
lcc compiler) or the CPU time used (for the gcc compiler). The
|
||||||
|
argument is assigned the time since the last call to this function. */
|
||||||
|
double getRunTime(double *timeSinceLastCall);
|
||||||
|
|
||||||
|
/* Call before exiting to free memory allocated by this module */
|
||||||
|
void freeInOu(void); /* 4-May-2017 Ari Ferrera */
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMINOU_H_*/
|
87
mmmaci.c
Normal file
87
mmmaci.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2005 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/* Macintosh interface functions */
|
||||||
|
/***********************************/
|
||||||
|
|
||||||
|
#ifdef THINK_C
|
||||||
|
|
||||||
|
#include "mmmaci.h"
|
||||||
|
|
||||||
|
#define kBaseResID 128
|
||||||
|
#define kMoveToFront (WindowPtr)-1L
|
||||||
|
|
||||||
|
#define kHorizontalPixel 30
|
||||||
|
#define kVerticalPixel 50
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Macintosh tool box initialization */
|
||||||
|
void ToolBoxInit(void)
|
||||||
|
{
|
||||||
|
InitGraf(&thePort); /*??? Crashes console interface */
|
||||||
|
InitFonts();
|
||||||
|
InitWindows();
|
||||||
|
InitMenus();
|
||||||
|
TEInit();
|
||||||
|
InitDialogs(nil);
|
||||||
|
InitCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Macintosh window initialization */
|
||||||
|
void WindowInit(void)
|
||||||
|
{
|
||||||
|
WindowPtr window;
|
||||||
|
window = GetNewWindow(kBaseResID, nil, kMoveToFront);
|
||||||
|
if (window == nil)
|
||||||
|
{
|
||||||
|
SysBeep(10); /* Couldn't load the WIND resource!!! */
|
||||||
|
ExitToShell();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowWindow(window);
|
||||||
|
SetPort(window);
|
||||||
|
/* MoveTo(kHorizontalPixel, kVerticalPixel); */
|
||||||
|
/* DrawString("\pHello, world!"); */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the opening window */
|
||||||
|
void DrawMyPicture(void)
|
||||||
|
{
|
||||||
|
Rect pictureRect;
|
||||||
|
WindowPtr window;
|
||||||
|
PicHandle picture;
|
||||||
|
|
||||||
|
window = FrontWindow();
|
||||||
|
pictureRect = window->portRect;
|
||||||
|
picture = GetPicture(kBaseResID);
|
||||||
|
|
||||||
|
if (picture == nil) {
|
||||||
|
SysBeep(10); /* Couldn't load the PICT resource!!! */
|
||||||
|
ExitToShell();
|
||||||
|
}
|
||||||
|
|
||||||
|
CenterPict(picture, &pictureRect);
|
||||||
|
DrawPicture(picture, &pictureRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Center picture */
|
||||||
|
void CenterPict(PicHandle picture, Rect *destRectPtr)
|
||||||
|
{
|
||||||
|
Rect windRect, pictRect;
|
||||||
|
windRect = *destRectPtr;
|
||||||
|
pictRect = (**(picture)).picFrame;
|
||||||
|
OffsetRect(&pictRect, windRect.left - pictRect.left,
|
||||||
|
windRect.top - pictRect.top);
|
||||||
|
OffsetRect(&pictRect, (windRect.right - pictRect.right)/2,
|
||||||
|
(windRect.bottom - pictRect.bottom)/2);
|
||||||
|
*destRectPtr = pictRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* end ifdef THINK_C */
|
20
mmmaci.h
Normal file
20
mmmaci.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2005 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/* Macintosh interface functions */
|
||||||
|
/***********************************/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMMACI_H_
|
||||||
|
#define METAMATH_MMMACI_H_
|
||||||
|
|
||||||
|
void ToolBoxInit(void);
|
||||||
|
void WindowInit(void);
|
||||||
|
void DrawMyPicture(void);
|
||||||
|
|
||||||
|
void CenterPict(PicHandle picture, Rect *destRectPtr);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMMACI_H_ */
|
214
mmpars.h
Normal file
214
mmpars.h
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2018 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMPARS_H_
|
||||||
|
#define METAMATH_MMPARS_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
char *readRawSource(/*vstring inputFn,*/ /* 2-Feb-2018 nm Unused argument */
|
||||||
|
vstring inputBuf, long *size);
|
||||||
|
void parseKeywords(void);
|
||||||
|
void parseLabels(void);
|
||||||
|
void parseMathDecl(void);
|
||||||
|
void parseStatements(void);
|
||||||
|
char parseProof(long statemNum);
|
||||||
|
char parseCompressedProof(long statemNum);
|
||||||
|
nmbrString *getProof(long statemNum, flag printFlag);
|
||||||
|
|
||||||
|
void rawSourceError(char *startFile, char *ptr, long tokenLen,
|
||||||
|
/*long lineNum,*/ /* 2-Feb-2018 nm */
|
||||||
|
/*vstring fileName,*/ vstring errMsg); /* 2-Feb-2018 nm */
|
||||||
|
void sourceError(char *ptr, long tokenLen, long stmtNum, vstring errMsg);
|
||||||
|
void mathTokenError(long tokenNum /* 0 is 1st one */,
|
||||||
|
nmbrString *tokenList, long stmtNum, vstring errMsg);
|
||||||
|
vstring shortDumpRPNStack(void);
|
||||||
|
|
||||||
|
/* Label comparison for qsort */
|
||||||
|
int labelSortCmp(const void *key1, const void *key2);
|
||||||
|
|
||||||
|
/* Label comparison for bsearch */
|
||||||
|
int labelSrchCmp(const void *key, const void *data);
|
||||||
|
|
||||||
|
/* Math token comparison for qsort */
|
||||||
|
int mathSortCmp(const void *key1, const void *key2);
|
||||||
|
|
||||||
|
/* Math token label comparison for bsearch */
|
||||||
|
int mathSrchCmp(const void *key, const void *data);
|
||||||
|
|
||||||
|
/* Hypothesis and local label comparison for qsort */
|
||||||
|
int hypAndLocSortCmp(const void *key1, const void *key2);
|
||||||
|
|
||||||
|
/* Hypothesis and local label comparison for bsearch */
|
||||||
|
int hypAndLocSrchCmp(const void *key, const void *data);
|
||||||
|
|
||||||
|
/* This function returns the length of the white space starting at ptr.
|
||||||
|
Comments are considered white space. ptr should point to the first character
|
||||||
|
of the white space. If ptr does not point to a white space character, 0
|
||||||
|
is returned. If ptr points to a null character, 0 is returned. */
|
||||||
|
long whiteSpaceLen(char *ptr);
|
||||||
|
|
||||||
|
/* 31-Dec-2017 nm For .mm file splitting */
|
||||||
|
/* Like whiteSpaceLen except comments are not whitespace */
|
||||||
|
long rawWhiteSpaceLen(char *ptr);
|
||||||
|
|
||||||
|
/* This function returns the length of the token (non-white-space) starting at
|
||||||
|
ptr. Comments are considered white space. ptr should point to the first
|
||||||
|
character of the token. If ptr points to a white space character, 0
|
||||||
|
is returned. If ptr points to a null character, 0 is returned. If ptr
|
||||||
|
points to a keyword, 0 is returned. A keyword ends a token. */
|
||||||
|
long tokenLen(char *ptr);
|
||||||
|
|
||||||
|
/* Unlike tokenLen(), keywords are not treated as special. In particular:
|
||||||
|
if ptr points to a keyword, 0 is NOT returned (instead, 2 is returned),
|
||||||
|
and a keyword does NOT end a token (which is a relic of days before
|
||||||
|
whitespace surrounding a token was part of the spec, but still serves
|
||||||
|
a useful purpose in token() for friendlier error detection). */
|
||||||
|
long rawTokenLen(char *ptr);
|
||||||
|
|
||||||
|
/* This function returns the length of the proof token starting at
|
||||||
|
ptr. Comments are considered white space. ptr should point to the first
|
||||||
|
character of the token. If ptr points to a white space character, 0
|
||||||
|
is returned. If ptr points to a null character, 0 is returned. If ptr
|
||||||
|
points to a keyword, 0 is returned. A keyword ends a token.
|
||||||
|
":" is considered a token. */
|
||||||
|
long proofTokenLen(char *ptr);
|
||||||
|
|
||||||
|
/* 9-Jan-2018 nm */
|
||||||
|
/* Counts the number of \n between start for length chars.
|
||||||
|
If length = -1, then use end-of-string 0 to stop.
|
||||||
|
If length >= 0, then scan at most length chars, but stop
|
||||||
|
if end-of-string 0 is found. */
|
||||||
|
long countLines(vstring start, long length);
|
||||||
|
|
||||||
|
/* Array with sort keys for all possible labels, including the ones for
|
||||||
|
hypotheses (which may not always be active) */
|
||||||
|
/* This array is used to see if any label is used anywhere, and is used
|
||||||
|
to make sure there are no conflicts when local labels inside of compact
|
||||||
|
proofs are generated. */
|
||||||
|
extern long *g_allLabelKeyBase;
|
||||||
|
extern long g_numAllLabelKeys;
|
||||||
|
|
||||||
|
/* Working structure for parsing proofs */
|
||||||
|
/* This structure should be deallocated by the ERASE command. */
|
||||||
|
extern long g_wrkProofMaxSize; /* Maximum size so far - it may grow */
|
||||||
|
struct sortHypAndLoc { /* Used for sorting hypAndLocLabel field */
|
||||||
|
long labelTokenNum;
|
||||||
|
void *labelName;
|
||||||
|
};
|
||||||
|
struct wrkProof_struct {
|
||||||
|
long numTokens; /* Number of tokens in proof */
|
||||||
|
long numSteps; /* Number of steps in proof */
|
||||||
|
long numLocalLabels; /* Number of local labels */
|
||||||
|
long numHypAndLoc; /* Number of active hypotheses and local labels */
|
||||||
|
char *localLabelPoolPtr; /* Next free location in local label pool */
|
||||||
|
long RPNStackPtr; /* Offset of end of RPNStack */
|
||||||
|
long errorCount; /* Errors in proof - used to suppress too many error msgs */
|
||||||
|
flag errorSeverity; /* 0 = OK, 1 = unk step, 2 = error, 3 = severe error,
|
||||||
|
4 = not a $p statement */
|
||||||
|
|
||||||
|
/* The following pointers will always be allocated with g_wrkProofMaxSize
|
||||||
|
entries. If a function needs more than g_wrkProofMaxSize, it must
|
||||||
|
reallocate all of these and increase g_wrkProofMaxSize. */
|
||||||
|
nmbrString *tokenSrcPtrNmbr; /* Source parsed into tokens vs. token number
|
||||||
|
- token size */
|
||||||
|
pntrString *tokenSrcPtrPntr; /* Source parsed into tokens vs. token number
|
||||||
|
- token src ptrs */
|
||||||
|
nmbrString *stepSrcPtrNmbr; /* Pointer to label token in source file
|
||||||
|
vs. step number - label size */
|
||||||
|
pntrString *stepSrcPtrPntr; /* Pointer to label token in source file
|
||||||
|
vs. step number - label src ptrs */
|
||||||
|
flag *localLabelFlag; /* 1 means step has a local label declaration */
|
||||||
|
struct sortHypAndLoc *hypAndLocLabel;
|
||||||
|
/* Sorted ptrs to hyp and local label names + token# */
|
||||||
|
char *localLabelPool; /* String pool to hold local labels */
|
||||||
|
nmbrString *proofString; /* The proof in RPN - statement # if > 0
|
||||||
|
or -(step # + 1000) of local label decl if < -1 */
|
||||||
|
pntrString *mathStringPtrs; /* Ptr to math string vs. each step */
|
||||||
|
/* (Allocated in verifyProof() as needed by nmbrLet()) */
|
||||||
|
nmbrString *RPNStack; /* Stack for RPN parsing */
|
||||||
|
|
||||||
|
/* For compressed proof parsing */
|
||||||
|
nmbrString *compressedPfLabelMap; /* Map from compressed label to actual */
|
||||||
|
long compressedPfNumLabels; /* Number of compressed labels */
|
||||||
|
|
||||||
|
};
|
||||||
|
extern struct wrkProof_struct g_WrkProof;
|
||||||
|
|
||||||
|
/* Converts an ASCII string to a nmbrString of math symbols. statemNum
|
||||||
|
provides the context for the parse (to get correct active symbols) */
|
||||||
|
nmbrString *parseMathTokens(vstring userText, long statemNum);
|
||||||
|
|
||||||
|
/* 12-Jun-2011 nm Added reformatFlag */
|
||||||
|
vstring outputStatement(long stmt, /*flag cleanFlag,*/ flag reformatFlag);
|
||||||
|
/* 12-Jun-2011 nm */
|
||||||
|
/* Caller must deallocate return string */
|
||||||
|
vstring rewrapComment(vstring comment);
|
||||||
|
|
||||||
|
/* 10/10/02 */
|
||||||
|
/* Lookup $a or $p label and return statement number.
|
||||||
|
Return -1 if not found. */
|
||||||
|
long lookupLabel(vstring label);
|
||||||
|
|
||||||
|
/* 31-Dec-2017 nm For file splitting */
|
||||||
|
|
||||||
|
/* Get the next real $[...$] or virtual $( Begin $[... inclusion */
|
||||||
|
void getNextInclusion(char *fileBuf, long startOffset, /* inputs */
|
||||||
|
/* outputs: */
|
||||||
|
long *cmdPos1, long *cmdPos2,
|
||||||
|
long *endPos1, long *endPos2,
|
||||||
|
char *cmdType, /* 'B' = "$( Begin [$..." through "$( End [$...",
|
||||||
|
'I' = "[$...",
|
||||||
|
'S' = "$( Skip [$...",
|
||||||
|
'E' = Start missing matched End
|
||||||
|
'N' = no include found */
|
||||||
|
vstring *fileName /* name of included file */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* This function transfers the content of the statement[] array
|
||||||
|
to a linear buffer in preparation for creating the output file. */
|
||||||
|
vstring writeSourceToBuffer(void);
|
||||||
|
|
||||||
|
/* 31-Dec-2017 nm */
|
||||||
|
/* This function creates split files containing $[ $] inclusions, from
|
||||||
|
a nonsplit source with $( Begin $[... etc. inclusions */
|
||||||
|
/* Note that *fileBuf is assigned to the empty string upon return, to
|
||||||
|
conserve memory */
|
||||||
|
void writeSplitSource(vstring *fileBuf, vstring fileName,
|
||||||
|
flag noVersioningFlag, flag noDeleteFlag);
|
||||||
|
|
||||||
|
/* When "write source" does not have the "/split" qualifier, by default
|
||||||
|
(i.e. without "/no_delete") the included modules are "deleted" (renamed
|
||||||
|
to ~1) since their content will be in the main output file. */
|
||||||
|
void deleteSplits(vstring *fileBuf, flag noVersioningFlag);
|
||||||
|
|
||||||
|
/* 9-Jan-2018 nm */
|
||||||
|
/* Get file name and line number given a pointer into the read buffer */
|
||||||
|
/* The user must deallocate the returned string (file name) */
|
||||||
|
/* The globals includeCall structure and includeCalls are used */
|
||||||
|
vstring getFileAndLineNum(vstring buffPtr/*start of read buffer*/,
|
||||||
|
vstring currentPtr/*place at which to get file name and line no*/,
|
||||||
|
long *lineNum/*return argument*/);
|
||||||
|
|
||||||
|
/* 9-Jan-2018 nm */
|
||||||
|
/* statement[stmtNum].fileName and .lineNum are initialized to "" and 0.
|
||||||
|
To save CPU time, they aren't normally assigned until needed, but once
|
||||||
|
assigned they can be reused without looking them up again. This function
|
||||||
|
will assign them if they haven't been assigned yet. It just returns if
|
||||||
|
they have already been assigned. */
|
||||||
|
/* The globals statement[] and sourcePtr are used */
|
||||||
|
void assignStmtFileAndLineNum(long stmtNum);
|
||||||
|
|
||||||
|
/* Initial read of source file */
|
||||||
|
vstring readSourceAndIncludes(vstring inputFn, long *size);
|
||||||
|
|
||||||
|
/* Recursively expand the source of an included file */
|
||||||
|
char *readInclude(vstring fileBuf, long fileBufOffset,
|
||||||
|
/*vstring inclFileName,*/ vstring sourceFileName,
|
||||||
|
long *size, long parentLineNum, flag *errorFlag);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMPARS_H_ */
|
217
mmpfas.h
Normal file
217
mmpfas.h
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2020 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMPFAS_H_
|
||||||
|
#define METAMATH_MMPFAS_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
extern long g_proveStatement; /* The statement to be proved */
|
||||||
|
extern flag g_proofChangedFlag; /* Flag to push 'undo' stack */
|
||||||
|
|
||||||
|
extern long g_userMaxProveFloat; /* Upper limit for proveFloating */
|
||||||
|
|
||||||
|
extern long g_dummyVars; /* The number of dummy variables currently declared */
|
||||||
|
extern long g_pipDummyVars; /* Number of dummy vars used by proof in progress */
|
||||||
|
|
||||||
|
/* Structure for holding a proof in progress. */
|
||||||
|
/* This structure should be deallocated after use. */
|
||||||
|
struct pip_struct {
|
||||||
|
nmbrString *proof; /* The proof itself */
|
||||||
|
pntrString *target; /* Left hand side of = in display */
|
||||||
|
pntrString *source; /* Right hand side of = in display */
|
||||||
|
pntrString *user; /* User-specified math string assignments to step */
|
||||||
|
};
|
||||||
|
extern struct pip_struct g_ProofInProgress;
|
||||||
|
|
||||||
|
/* Interactively select statement assignments that match */
|
||||||
|
/* maxEssential is the maximum number of essential hypotheses that a
|
||||||
|
statement may have in order to be included in the matched list. */
|
||||||
|
void interactiveMatch(long step, long maxEssential);
|
||||||
|
|
||||||
|
/* Assign a statement to an unknown proof step */
|
||||||
|
void assignStatement(long statemNum, long step);
|
||||||
|
|
||||||
|
/* Find proof of formula by using the replaceStatement() algorithm i.e.
|
||||||
|
see if any statement matches current step AND each of its hypotheses
|
||||||
|
matches a proof in progress hypothesis or some step already in the proof.
|
||||||
|
If a proof is found, it is returned, otherwise an empty (length 0) proof is
|
||||||
|
returned. */
|
||||||
|
/* The caller must deallocate the returned nmbrString. */
|
||||||
|
nmbrString *proveByReplacement(long prfStmt,
|
||||||
|
long prfStep, /* 0 means step 1 */
|
||||||
|
flag noDistinct, /* 1 means don't try statements with $d's */
|
||||||
|
flag dummyVarFlag, /* 0 means no dummy vars are in prfStmt */
|
||||||
|
flag searchMethod, /* 1 means to try proveFloating on $e's also */
|
||||||
|
long improveDepth,
|
||||||
|
flag overrideFlag, /* 1 means to override usage locks */ /* 3-May-2016 nm */
|
||||||
|
flag mathboxFlag /* 1 means allow mathboxes */ /* 5-Aug-2020 nm */
|
||||||
|
);
|
||||||
|
|
||||||
|
nmbrString *replaceStatement(long replStatemNum,
|
||||||
|
long prfStep,
|
||||||
|
long provStmtNum,
|
||||||
|
flag subProofFlag, /* If 1, then scan only subproof at prfStep to look for
|
||||||
|
matches, instead of whole proof, for faster speed (used by MINIMIZE_WITH) */
|
||||||
|
flag noDistinct, /* 1 means don't try statements with $d's */
|
||||||
|
flag searchMethod, /* 1 means to try proveFloating on $e's also */
|
||||||
|
long improveDepth,
|
||||||
|
flag overrideFlag, /* 1 means to override usage locks */ /* 3-May-2016 nm */
|
||||||
|
flag mathboxFlag /* 1 means allow mathboxes */ /* 5-Aug-2020 nm */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* 22-Aug-2012 nm Added this function */
|
||||||
|
/* This function identifies all steps in the proof in progress that (1) are
|
||||||
|
independent of step refStep, (2) have no dummy variables, (3) are
|
||||||
|
not $f's or $e's, and (4) have subproofs that are complete
|
||||||
|
(no unassigned steps). A "Y" is returned for each such step,
|
||||||
|
and "N" is returned for all other steps. The "Y" steps can be used
|
||||||
|
for scanning for useful subproofs outside of the subProof of refStep.
|
||||||
|
Note: The caller must deallocate the returned vstring. */
|
||||||
|
vstring getIndepKnownSteps(long proofStmt, long refStep);
|
||||||
|
|
||||||
|
/* 22-Aug-2012 nm Added this function */
|
||||||
|
/* This function classifies each proof step in g_ProofInProgress.proof
|
||||||
|
as known or unknown ('K' or 'U' in the returned string) depending
|
||||||
|
on whether the step has a completely known subproof.
|
||||||
|
Note: The caller must deallocate the returned vstring. */
|
||||||
|
vstring getKnownSubProofs(void);
|
||||||
|
|
||||||
|
/* Add a subproof in place of an unknown step to g_ProofInProgress. The
|
||||||
|
.target, .source, and .user fields are initialized to empty (except
|
||||||
|
.target of the deleted unknown step is retained). */
|
||||||
|
void addSubProof(nmbrString *subProof, long step);
|
||||||
|
|
||||||
|
/* 11-Sep-2016 nm */
|
||||||
|
/* This function eliminates any occurrences of statement sourceStmtNum in the
|
||||||
|
targetProof by substituting it with the proof of sourceStmtNum. An empty
|
||||||
|
nmbrString is returned if there was an error. */
|
||||||
|
/* Normally, targetProof is the global g_ProofInProgress.proof. However,
|
||||||
|
we make it an argument in case in the future we'd like to do this
|
||||||
|
outside of the proof assistant. */
|
||||||
|
nmbrString *expandProof(nmbrString *targetProof,
|
||||||
|
long sourceStmtNum /*, long targetStmtNum*/);
|
||||||
|
|
||||||
|
/* Delete a subproof starting (in reverse from) step. The step is replaced
|
||||||
|
with an unknown step, and its .target field is retained. */
|
||||||
|
void deleteSubProof(long step);
|
||||||
|
|
||||||
|
/* Check to see if a statement will match the g_ProofInProgress.target (or .user)
|
||||||
|
of an unknown step. Returns 1 if match, 0 if not, 2 if unification
|
||||||
|
timed out. */
|
||||||
|
char checkStmtMatch(long statemNum, long step);
|
||||||
|
|
||||||
|
/* Check to see if a (user-specified) math string will match the
|
||||||
|
g_ProofInProgress.target (or .user) of an step. Returns 1 if match, 0 if
|
||||||
|
not, 2 if unification timed out. */
|
||||||
|
char checkMStringMatch(nmbrString *mString, long step);
|
||||||
|
|
||||||
|
/* Find proof of formula or simple theorem (no new vars in $e's) */
|
||||||
|
/* maxEDepth is the maximum depth at which statements with $e hypotheses are
|
||||||
|
considered. A value of 0 means none are considered. */
|
||||||
|
nmbrString *proveFloating(nmbrString *mString, long statemNum, long maxEDepth,
|
||||||
|
long step, flag noDistinct,
|
||||||
|
/* 3-May-2016 nm */
|
||||||
|
flag overrideFlag, /* 0 means respect usage locks
|
||||||
|
1 means to override usage locks
|
||||||
|
2 means override silently */
|
||||||
|
flag mathboxFlag /* 1 means allow mathboxes */ /* 5-Aug-2020 nm */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* 22-Aug-2012 nm Added this function */
|
||||||
|
/* This function does quick check for some common conditions that prevent
|
||||||
|
a trial statement (scheme) from being unified with a given instance.
|
||||||
|
Return value 0 means it can't be unified, 1 means it might be unifiable. */
|
||||||
|
char quickMatchFilter(long trialStmt, nmbrString *mString,
|
||||||
|
long dummyVarFlag /* 0 if no dummy vars in mString */);
|
||||||
|
|
||||||
|
/* Shorten proof by using specified statement. */
|
||||||
|
void minimizeProof(long repStatemNum, long prvStatemNum, flag
|
||||||
|
allowGrowthFlag);
|
||||||
|
|
||||||
|
/* Initialize g_ProofInProgress.source of the step, and .target of all
|
||||||
|
hypotheses, to schemes using new dummy variables. */
|
||||||
|
void initStep(long step);
|
||||||
|
|
||||||
|
/* Look for completely known subproofs in g_ProofInProgress.proof and
|
||||||
|
assign g_ProofInProgress.target and .source. Calls assignKnownSteps(). */
|
||||||
|
void assignKnownSubProofs(void);
|
||||||
|
|
||||||
|
/* This function assigns math strings to all steps (g_ProofInProgress.target and
|
||||||
|
.source fields) in a subproof with all known steps. */
|
||||||
|
void assignKnownSteps(long startStep, long sbProofLen);
|
||||||
|
|
||||||
|
/* Interactive unify a step. Calls interactiveUnify(). */
|
||||||
|
/* If messageFlag is 1, a message will be issued if the
|
||||||
|
step is already unified. If messageFlag is 0, show the step #
|
||||||
|
being unified. If messageFlag is 2, don't print step #, and do nothing
|
||||||
|
if step is already unified. */
|
||||||
|
void interactiveUnifyStep(long step, char messageFlag);
|
||||||
|
|
||||||
|
/* Interactively select one of several possible unifications */
|
||||||
|
/* Returns: 0 = no unification possible
|
||||||
|
1 = unification was selected; held in stateVector
|
||||||
|
2 = unification timed out
|
||||||
|
3 = no unification was selected */
|
||||||
|
char interactiveUnify(nmbrString *schemeA, nmbrString *schemeB,
|
||||||
|
pntrString **stateVector);
|
||||||
|
|
||||||
|
/* Automatically unify steps with unique unification */
|
||||||
|
void autoUnify(flag congrats);
|
||||||
|
|
||||||
|
/* Make stateVector substitutions in all steps. The stateVector must
|
||||||
|
contain the result of a valid unification. */
|
||||||
|
void makeSubstAll(pntrString *stateVector);
|
||||||
|
|
||||||
|
/* Replace a dummy variable with a user-specified math string */
|
||||||
|
void replaceDummyVar(long dummyVar, nmbrString *mString);
|
||||||
|
|
||||||
|
/* Get subproof length of a proof, starting at endStep and going backwards */
|
||||||
|
long subproofLen(nmbrString *proof, long endStep);
|
||||||
|
|
||||||
|
/* 25-Aug-2012 nm Added this function */
|
||||||
|
/* If testStep has no dummy variables, return 0;
|
||||||
|
if testStep has isolated dummy variables (that don't affect rest of
|
||||||
|
proof), return 1;
|
||||||
|
if testStep has dummy variables used elsewhere in proof, return 2 */
|
||||||
|
char checkDummyVarIsolation(long testStep); /* 0=1st step, 1=2nd, etc. */
|
||||||
|
|
||||||
|
/* 25-Aug-2012 nm Added this function */
|
||||||
|
/* Given a starting step, find its parent (the step it is a hypothesis of) */
|
||||||
|
/* If the starting step is the last proof step, just return it */
|
||||||
|
long getParentStep(long startStep); /* 0=1st step, 1=2nd, etc. */
|
||||||
|
|
||||||
|
/* Adds a dummy variable to end of mathToken array */
|
||||||
|
/* (Note: it now grows forever, but purging it might worsen fragmentation) */
|
||||||
|
void declareDummyVars(long numNewVars);
|
||||||
|
|
||||||
|
/* Copies the Proof Assistant proof state */
|
||||||
|
void copyProofStruct(struct pip_struct *outProofStruct,
|
||||||
|
struct pip_struct inProofStruct);
|
||||||
|
|
||||||
|
/* Initiailizes the Proof Assistant proof state */
|
||||||
|
void initProofStruct(struct pip_struct *proofStruct, nmbrString *proof,
|
||||||
|
long proveStatement);
|
||||||
|
|
||||||
|
/* Clears the Proof Assistant proof state */
|
||||||
|
void deallocProofStruct(struct pip_struct *proofStruct);
|
||||||
|
|
||||||
|
/* Actions for processUndoStack() */
|
||||||
|
#define PUS_INIT 1
|
||||||
|
#define PUS_PUSH 2
|
||||||
|
#define PUS_UNDO 3
|
||||||
|
#define PUS_REDO 4
|
||||||
|
#define PUS_NEW_SIZE 5
|
||||||
|
#define PUS_GET_SIZE 6
|
||||||
|
#define PUS_GET_STATUS 7
|
||||||
|
/* Handle the PUSH, UNDO, and REDO commands */
|
||||||
|
long processUndoStack(struct pip_struct *proofStruct,
|
||||||
|
char action,
|
||||||
|
vstring info, /* Info to print upon UNDO or REDO */
|
||||||
|
long newStackSize); /* Used only by NEW_SIZE */
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMPFAS_H_ */
|
104
mmunif.h
Normal file
104
mmunif.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2020 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMUNIF_H_
|
||||||
|
#define METAMATH_MMUNIF_H_
|
||||||
|
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
extern long g_minSubstLen; /* User-settable value - 0 or 1 */
|
||||||
|
extern long g_userMaxUnifTrials;
|
||||||
|
/* User-defined upper limit (# backtracks) for unification trials */
|
||||||
|
extern long g_unifTrialCount;
|
||||||
|
/* 0 means don't time out; 1 means start counting trials */
|
||||||
|
extern long g_unifTimeouts; /* Number of timeouts so far for this command */
|
||||||
|
extern flag g_hentyFilter; /* Turns Henty filter on or off */
|
||||||
|
|
||||||
|
/* 26-Sep-2010 nm */
|
||||||
|
extern flag g_bracketMatchInit; /* So eraseSource() (mmcmds.c) can clr it */
|
||||||
|
|
||||||
|
/* 1-Oct-2017 nm Made this global so eraseSource() (mmcmds.c) can clr it */
|
||||||
|
extern nmbrString *g_firstConst;
|
||||||
|
/* 2-Oct-2017 nm Made these global so eraseSource() (mmcmds.c) can clr them */
|
||||||
|
extern nmbrString *g_lastConst;
|
||||||
|
extern nmbrString *g_oneConst;
|
||||||
|
|
||||||
|
|
||||||
|
nmbrString *makeSubstUnif(flag *newVarFlag,
|
||||||
|
nmbrString *trialScheme, pntrString *stateVector);
|
||||||
|
|
||||||
|
|
||||||
|
char unify(
|
||||||
|
nmbrString *schemeA,
|
||||||
|
nmbrString *schemeB,
|
||||||
|
/* nmbrString **unifiedScheme, */ /* stateVector[8] holds this */
|
||||||
|
pntrString **stateVector,
|
||||||
|
long reEntryFlag);
|
||||||
|
/* This function unifies two math token strings, schemeA and
|
||||||
|
schemeB. The result is contained in unifiedScheme.
|
||||||
|
0 is returned if no assignment is possible.
|
||||||
|
If reEntryFlag is 1, the next possible set of assignments, if any,
|
||||||
|
is returned. 2 is returned if the unification times out.
|
||||||
|
(*stateVector) contains the state of the previous
|
||||||
|
call. It is the caller's responsibility to deallocate the
|
||||||
|
contents of (*stateVector) when done, UNLESS a 0 is returned.
|
||||||
|
The caller must assign (*stateVector) to a legal pntrString
|
||||||
|
(e.g. NULL_PNTRSTRING) before calling.
|
||||||
|
|
||||||
|
All variables with a tokenNum > saveMathTokens are assumed
|
||||||
|
to be "unknown" variables that can be assigned; all other
|
||||||
|
variables are treated like constants in the unification
|
||||||
|
algorithm.
|
||||||
|
|
||||||
|
The "unknown" variable assignments are contained in (*stateVector)
|
||||||
|
(which is a complex structure, described below). Some "unknown"
|
||||||
|
variables may have no assignment, in which case they will
|
||||||
|
remain "unknown", and others may have assignments which include
|
||||||
|
"unknown" variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* oneDirUnif() is like unify(), except that when reEntryFlag is 1,
|
||||||
|
a new unification is returned ONLY if the assignments to the
|
||||||
|
variables in schemeA have changed. This is used to speed up the
|
||||||
|
program. */
|
||||||
|
flag oneDirUnif(
|
||||||
|
nmbrString *schemeA,
|
||||||
|
nmbrString *schemeB,
|
||||||
|
pntrString **stateVector,
|
||||||
|
long reEntryFlag);
|
||||||
|
|
||||||
|
|
||||||
|
/* uniqueUnif() is like unify(), but there is no reEntryFlag, and 3 possible
|
||||||
|
values are returned:
|
||||||
|
0: no unification was possible.
|
||||||
|
1: exactly one unification was possible, and stateVector is valid.
|
||||||
|
2: unification timed out.
|
||||||
|
3: more than one unification was possible. */
|
||||||
|
char uniqueUnif(
|
||||||
|
nmbrString *schemeA,
|
||||||
|
nmbrString *schemeB,
|
||||||
|
pntrString **stateVector);
|
||||||
|
|
||||||
|
/* unifyH() is like unify(), except that when reEntryFlag is 1,
|
||||||
|
a new unification is returned ONLY if the normalized unification
|
||||||
|
does not previously exist in the "Henty filter". This reduces
|
||||||
|
ambiguous unifications. The values returned are the same as
|
||||||
|
those returned by unify(). (The elimination of equivalent
|
||||||
|
unifications was suggested by Jeremy Henty.) */
|
||||||
|
char unifyH(
|
||||||
|
nmbrString *schemeA,
|
||||||
|
nmbrString *schemeB,
|
||||||
|
pntrString **stateVector,
|
||||||
|
long reEntryFlag);
|
||||||
|
|
||||||
|
/* Cleans out a stateVector if not empty */
|
||||||
|
void purgeStateVector(pntrString **stateVector);
|
||||||
|
|
||||||
|
/* Prints the substitutions determined by unify for debugging purposes */
|
||||||
|
void printSubst(pntrString *stateVector);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMUNIF_H_ */
|
15
mmutil.c
Normal file
15
mmutil.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2005 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* This is a collection of useful functions
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* (This file is currently empty.) */
|
||||||
|
/* The include makes file non-empty for ANSI compliance. */
|
||||||
|
#include <stdio.h>
|
7
mmutil.h
Normal file
7
mmutil.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2005 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/* (This file is currently empty.) */
|
895
mmveri.c
Normal file
895
mmveri.c
Normal file
@ -0,0 +1,895 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2017 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
#include "mminou.h"
|
||||||
|
#include "mmpars.h"
|
||||||
|
#include "mmveri.h"
|
||||||
|
|
||||||
|
/* Global structure used for getting information about a step */
|
||||||
|
/* If getStep.stepNum is nonzero, we should get info about that step. */
|
||||||
|
struct getStep_struct getStep = {0, 0, 0, 0, 0,
|
||||||
|
NULL_NMBRSTRING, NULL_NMBRSTRING, NULL_PNTRSTRING, NULL_NMBRSTRING,
|
||||||
|
NULL_PNTRSTRING};
|
||||||
|
|
||||||
|
/* Verify proof of one statement in source file. Uses wrkProof structure.
|
||||||
|
Assumes that parseProof() has just been called for this statement. */
|
||||||
|
/* Returns 0 if proof is OK; 1 if proof is incomplete (has '?' tokens);
|
||||||
|
returns 2 if error found; returns 3 if not severe error
|
||||||
|
found; returns 4 if not a $p statement */
|
||||||
|
char verifyProof(long statemNum)
|
||||||
|
{
|
||||||
|
|
||||||
|
long stmt; /* Contents of proof string location */
|
||||||
|
long i, j, step;
|
||||||
|
char type;
|
||||||
|
char *fbPtr;
|
||||||
|
long tokenLength;
|
||||||
|
long numReqHyp;
|
||||||
|
char returnFlag = 0;
|
||||||
|
nmbrString *nmbrTmpPtr;
|
||||||
|
nmbrString *nmbrHypPtr;
|
||||||
|
nmbrString *bigSubstSchemeHyp = NULL_NMBRSTRING;
|
||||||
|
nmbrString *bigSubstInstHyp = NULL_NMBRSTRING;
|
||||||
|
flag unkHypFlag;
|
||||||
|
nmbrString *nmbrTmp = NULL_NMBRSTRING; /* Used to force tmp stack dealloc */
|
||||||
|
|
||||||
|
if (g_Statement[statemNum].type != p_) return (4); /* Do nothing if not $p */
|
||||||
|
|
||||||
|
/* Initialize pointers to math strings in RPN stack and vs. statement. */
|
||||||
|
/* (Must be initialized, even if severe error, to prevent crashes later.) */
|
||||||
|
for (i = 0; i < g_WrkProof.numSteps; i++) {
|
||||||
|
g_WrkProof.mathStringPtrs[i] = NULL_NMBRSTRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_WrkProof.errorSeverity > 2) return (g_WrkProof.errorSeverity);
|
||||||
|
/* Error too severe to check here */
|
||||||
|
g_WrkProof.RPNStackPtr = 0;
|
||||||
|
|
||||||
|
if (g_WrkProof.numSteps == 0) return (2);
|
||||||
|
/* Empty proof caused by error found by in parseProof */
|
||||||
|
|
||||||
|
for (step = 0; step < g_WrkProof.numSteps; step++) {
|
||||||
|
|
||||||
|
stmt = g_WrkProof.proofString[step];
|
||||||
|
|
||||||
|
/* Handle unknown proof steps */
|
||||||
|
if (stmt == -(long)'?') {
|
||||||
|
if (returnFlag < 1) returnFlag = 1;
|
||||||
|
/* Flag that proof is partially unknown */
|
||||||
|
/* Treat "?" like a hypothesis - push stack and continue */
|
||||||
|
g_WrkProof.RPNStack[g_WrkProof.RPNStackPtr] = step;
|
||||||
|
|
||||||
|
g_WrkProof.RPNStackPtr++;
|
||||||
|
/* Leave the step's math string empty and continue */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if the proof token is a local label ref. */
|
||||||
|
if (stmt < 0) {
|
||||||
|
/* It's a local label reference */
|
||||||
|
if (stmt > -1000) bug(2101);
|
||||||
|
i = -1000 - stmt; /* Get the step number it refers to */
|
||||||
|
|
||||||
|
/* Push the stack */
|
||||||
|
g_WrkProof.RPNStack[g_WrkProof.RPNStackPtr] = step;
|
||||||
|
g_WrkProof.RPNStackPtr++;
|
||||||
|
|
||||||
|
/* Assign a math string to the step (must not be deallocated by
|
||||||
|
cleanWrkProof()!) */
|
||||||
|
g_WrkProof.mathStringPtrs[step] =
|
||||||
|
g_WrkProof.mathStringPtrs[i];
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = g_Statement[stmt].type;
|
||||||
|
|
||||||
|
/* See if the proof token is a hypothesis */
|
||||||
|
if (type == e_ || type == f_) {
|
||||||
|
/* It's a hypothesis reference */
|
||||||
|
|
||||||
|
/* Push the stack */
|
||||||
|
g_WrkProof.RPNStack[g_WrkProof.RPNStackPtr] = step;
|
||||||
|
g_WrkProof.RPNStackPtr++;
|
||||||
|
|
||||||
|
/* Assign a math string to the step (must not be deallocated by
|
||||||
|
cleanWrkProof()!) */
|
||||||
|
g_WrkProof.mathStringPtrs[step] =
|
||||||
|
g_Statement[stmt].mathString;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The proof token must be an assertion */
|
||||||
|
if (type != a_ && type != p_) bug(2102);
|
||||||
|
|
||||||
|
/* It's an valid assertion. */
|
||||||
|
numReqHyp = g_Statement[stmt].numReqHyp;
|
||||||
|
nmbrHypPtr = g_Statement[stmt].reqHypList;
|
||||||
|
|
||||||
|
/* Assemble the hypotheses into two big math strings for unification */
|
||||||
|
/* Use a "dummy" token, the top of g_mathTokens array, to separate them. */
|
||||||
|
/* This is already done by the source parsing routines:
|
||||||
|
g_MathToken[g_mathTokens].tokenType = (char)con_;
|
||||||
|
g_MathToken[g_mathTokens].tokenName = "$|$"; */ /* Don't deallocate! */
|
||||||
|
|
||||||
|
nmbrLet(&bigSubstSchemeHyp, nmbrAddElement(NULL_NMBRSTRING, g_mathTokens));
|
||||||
|
nmbrLet(&bigSubstInstHyp, nmbrAddElement(NULL_NMBRSTRING, g_mathTokens));
|
||||||
|
unkHypFlag = 0; /* Flag that there are unknown hypotheses */
|
||||||
|
j = 0;
|
||||||
|
for (i = g_WrkProof.RPNStackPtr - numReqHyp; i < g_WrkProof.RPNStackPtr; i++) {
|
||||||
|
nmbrTmpPtr = g_WrkProof.mathStringPtrs[
|
||||||
|
g_WrkProof.RPNStack[i]];
|
||||||
|
if (nmbrTmpPtr[0] == -1) { /* If length is zero, hyp is unknown */
|
||||||
|
unkHypFlag = 1;
|
||||||
|
/* Assign scheme to empty nmbrString so it will always match instance */
|
||||||
|
nmbrLet(&bigSubstSchemeHyp,
|
||||||
|
nmbrCat(bigSubstSchemeHyp,
|
||||||
|
nmbrAddElement(nmbrTmpPtr, g_mathTokens), NULL));
|
||||||
|
} else {
|
||||||
|
nmbrLet(&bigSubstSchemeHyp,
|
||||||
|
nmbrCat(bigSubstSchemeHyp,
|
||||||
|
nmbrAddElement(g_Statement[nmbrHypPtr[j]].mathString,
|
||||||
|
g_mathTokens), NULL));
|
||||||
|
}
|
||||||
|
nmbrLet(&bigSubstInstHyp,
|
||||||
|
nmbrCat(bigSubstInstHyp,
|
||||||
|
nmbrAddElement(nmbrTmpPtr, g_mathTokens), NULL));
|
||||||
|
j++;
|
||||||
|
|
||||||
|
/* Get information about the step if requested */
|
||||||
|
if (getStep.stepNum) { /* If non-zero, step info is requested */
|
||||||
|
if (g_WrkProof.RPNStack[i] == getStep.stepNum - 1) {
|
||||||
|
/* Get parent of target if this is one of its hyp's */
|
||||||
|
getStep.targetParentStep = step + 1;
|
||||||
|
getStep.targetParentStmt = stmt;
|
||||||
|
}
|
||||||
|
if (step == getStep.stepNum - 1) {
|
||||||
|
/* Add to source hypothesis list */
|
||||||
|
nmbrLet(&getStep.sourceHyps, nmbrAddElement(getStep.sourceHyps,
|
||||||
|
g_WrkProof.RPNStack[i]));
|
||||||
|
}
|
||||||
|
} /* End of if (getStep.stepNum) */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*E*/if(db7)printLongLine(cat("step ", str((double)step+1), " sch ",
|
||||||
|
/*E*/ nmbrCvtMToVString(bigSubstSchemeHyp), NULL), "", " ");
|
||||||
|
/*E*/if(db7)printLongLine(cat("step ", str((double)step+1), " ins ",
|
||||||
|
/*E*/ nmbrCvtMToVString(bigSubstInstHyp), NULL), "", " ");
|
||||||
|
/* Unify the hypotheses of the scheme with their instances and assign
|
||||||
|
the variables of the scheme. If some of the hypotheses are unknown
|
||||||
|
(due to proof being debugged or previous error) we will try to unify
|
||||||
|
anyway; if the result is unique, we will use it. */
|
||||||
|
nmbrTmpPtr = assignVar(bigSubstSchemeHyp,
|
||||||
|
bigSubstInstHyp, stmt, statemNum, step, unkHypFlag);
|
||||||
|
/*E*/if(db7)printLongLine(cat("step ", str((double)step+1), " res ",
|
||||||
|
/*E*/ nmbrCvtMToVString(nmbrTmpPtr), NULL), "", " ");
|
||||||
|
|
||||||
|
/* Deallocate stack built up if there are many $d violations */
|
||||||
|
nmbrLet(&nmbrTmp, NULL_NMBRSTRING);
|
||||||
|
|
||||||
|
/* Assign the substituted assertion (must be deallocated by
|
||||||
|
cleanWrkProof()!) */
|
||||||
|
g_WrkProof.mathStringPtrs[step] = nmbrTmpPtr;
|
||||||
|
if (nmbrTmpPtr[0] == -1) {
|
||||||
|
if (!unkHypFlag) {
|
||||||
|
returnFlag = 2; /* An error occurred (assignVar printed it) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Pop the stack */
|
||||||
|
g_WrkProof.RPNStackPtr = g_WrkProof.RPNStackPtr - numReqHyp;
|
||||||
|
g_WrkProof.RPNStack[g_WrkProof.RPNStackPtr] = step;
|
||||||
|
g_WrkProof.RPNStackPtr++;
|
||||||
|
|
||||||
|
} /* Next step */
|
||||||
|
|
||||||
|
/* If there was a stack error, the verifier should have never been
|
||||||
|
called. */
|
||||||
|
if (g_WrkProof.RPNStackPtr != 1) bug(2108);
|
||||||
|
|
||||||
|
/* See if the result matches the statement to be proved */
|
||||||
|
if (returnFlag == 0) {
|
||||||
|
if (!nmbrEq(g_Statement[statemNum].mathString,
|
||||||
|
g_WrkProof.mathStringPtrs[g_WrkProof.numSteps - 1])) {
|
||||||
|
if (!g_WrkProof.errorCount) {
|
||||||
|
fbPtr = g_WrkProof.stepSrcPtrPntr[g_WrkProof.numSteps - 1];
|
||||||
|
tokenLength = g_WrkProof.stepSrcPtrNmbr[g_WrkProof.numSteps - 1];
|
||||||
|
/*??? Make sure suggested commands are correct. */
|
||||||
|
sourceError(fbPtr, tokenLength, statemNum, cat(
|
||||||
|
"The result of the proof (step ", str((double)(g_WrkProof.numSteps)),
|
||||||
|
") does not match the statement being proved. The result is \"",
|
||||||
|
nmbrCvtMToVString(
|
||||||
|
g_WrkProof.mathStringPtrs[g_WrkProof.numSteps - 1]),
|
||||||
|
"\" but the statement is \"",
|
||||||
|
nmbrCvtMToVString(g_Statement[statemNum].mathString),
|
||||||
|
"\". Type \"SHOW PROOF ",g_Statement[statemNum].labelName,
|
||||||
|
"\" to see the proof attempt.",NULL));
|
||||||
|
}
|
||||||
|
g_WrkProof.errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nmbrLet(&bigSubstSchemeHyp, NULL_NMBRSTRING);
|
||||||
|
nmbrLet(&bigSubstInstHyp, NULL_NMBRSTRING);
|
||||||
|
|
||||||
|
return (returnFlag);
|
||||||
|
|
||||||
|
} /* verifyProof */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* assignVar() finds an assignment to substScheme variables that match
|
||||||
|
the assumptions specified in the reason string */
|
||||||
|
nmbrString *assignVar(nmbrString *bigSubstSchemeAss,
|
||||||
|
nmbrString *bigSubstInstAss, long substScheme,
|
||||||
|
/* For error messages: */
|
||||||
|
long statementNum, long step, flag unkHypFlag)
|
||||||
|
{
|
||||||
|
nmbrString *bigSubstSchemeVars = NULL_NMBRSTRING;
|
||||||
|
nmbrString *substSchemeFrstVarOcc = NULL_NMBRSTRING;
|
||||||
|
nmbrString *varAssLen = NULL_NMBRSTRING;
|
||||||
|
nmbrString *substInstFrstVarOcc = NULL_NMBRSTRING;
|
||||||
|
nmbrString *result = NULL_NMBRSTRING; /* value returned */
|
||||||
|
long bigSubstSchemeLen,bigSubstInstLen,bigSubstSchemeVarLen,substSchemeLen,
|
||||||
|
resultLen;
|
||||||
|
long i,v,v1,p,q,tokenNum;
|
||||||
|
flag breakFlag, contFlag;
|
||||||
|
vstring tmpStr = "";
|
||||||
|
vstring tmpStr2 = "";
|
||||||
|
flag ambiguityCheckFlag = 0;
|
||||||
|
nmbrString *saveResult = NULL_NMBRSTRING;
|
||||||
|
|
||||||
|
/* Variables for disjoint variable ($d) check */
|
||||||
|
nmbrString *nmbrTmpPtrAS;
|
||||||
|
nmbrString *nmbrTmpPtrBS;
|
||||||
|
nmbrString *nmbrTmpPtrAIR;
|
||||||
|
nmbrString *nmbrTmpPtrBIR;
|
||||||
|
nmbrString *nmbrTmpPtrAIO;
|
||||||
|
nmbrString *nmbrTmpPtrBIO;
|
||||||
|
long dLen, pos, substAPos, substALen, instAPos, substBPos, substBLen,
|
||||||
|
instBPos, a, b, aToken, bToken, aToken2, bToken2, dILenR, dILenO,
|
||||||
|
optStart, reqStart;
|
||||||
|
flag foundFlag;
|
||||||
|
|
||||||
|
/* Variables for getting step info */
|
||||||
|
long j,k,m;
|
||||||
|
long numReqHyp;
|
||||||
|
nmbrString *nmbrHypPtr;
|
||||||
|
|
||||||
|
nmbrString *nmbrTmp = NULL_NMBRSTRING; /* Used to force tmp stack dealloc */
|
||||||
|
|
||||||
|
long nmbrSaveTempAllocStack;
|
||||||
|
|
||||||
|
/* Initialization to avoid compiler warnings (should not be theoretically
|
||||||
|
necessary) */
|
||||||
|
dILenR = 0;
|
||||||
|
dILenO = 0;
|
||||||
|
optStart = 0;
|
||||||
|
reqStart = 0;
|
||||||
|
nmbrTmpPtrAIR = NULL_NMBRSTRING;
|
||||||
|
nmbrTmpPtrBIR = NULL_NMBRSTRING;
|
||||||
|
nmbrTmpPtrAIO = NULL_NMBRSTRING;
|
||||||
|
nmbrTmpPtrBIO = NULL_NMBRSTRING;
|
||||||
|
|
||||||
|
nmbrSaveTempAllocStack = g_nmbrStartTempAllocStack;
|
||||||
|
g_nmbrStartTempAllocStack = g_nmbrTempAllocStackTop; /* For nmbrLet() stack cleanup*/
|
||||||
|
|
||||||
|
bigSubstSchemeLen = nmbrLen(bigSubstSchemeAss);
|
||||||
|
bigSubstInstLen = nmbrLen(bigSubstInstAss);
|
||||||
|
nmbrLet(&bigSubstSchemeVars,nmbrExtractVars(bigSubstSchemeAss));
|
||||||
|
bigSubstSchemeVarLen = nmbrLen(bigSubstSchemeVars);
|
||||||
|
|
||||||
|
/* If there are no variables in the hypotheses, there won't be any in the
|
||||||
|
assertion (unless there was a previously detected error). In this case,
|
||||||
|
the unification is just the assertion itself. */
|
||||||
|
if (!bigSubstSchemeVarLen) {
|
||||||
|
if (!nmbrLen(g_Statement[substScheme].reqVarList)) {
|
||||||
|
nmbrLet(&result,g_Statement[substScheme].mathString);
|
||||||
|
} else {
|
||||||
|
/* There must have been a previous error; let result remain empty */
|
||||||
|
if (!unkHypFlag) bug(2109);
|
||||||
|
}
|
||||||
|
goto returnPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate nmbrStrings used only to hold extra data for bigSubstSchemeAss;
|
||||||
|
don't use further nmbrString functions on them! */
|
||||||
|
/* substSchemeFrstVarOcc[] is the 1st occurrence of the variable
|
||||||
|
in bigSubstSchemeAss */
|
||||||
|
/* varAssLen[] is the length of the
|
||||||
|
assignment to the variable */
|
||||||
|
/* substInstFrstVarOcc[] is the 1st occurrence of the variable
|
||||||
|
in bigSubstInstAss */
|
||||||
|
nmbrLet(&substSchemeFrstVarOcc,nmbrSpace(bigSubstSchemeVarLen));
|
||||||
|
nmbrLet(&varAssLen,substSchemeFrstVarOcc);
|
||||||
|
nmbrLet(&substInstFrstVarOcc,substSchemeFrstVarOcc);
|
||||||
|
|
||||||
|
if (bigSubstSchemeVarLen != nmbrLen(g_Statement[substScheme].reqVarList)) {
|
||||||
|
if (unkHypFlag) {
|
||||||
|
/* If there are unknown hypotheses and all variables aren't present,
|
||||||
|
give up here */
|
||||||
|
goto returnPoint;
|
||||||
|
} else {
|
||||||
|
/* Actually, this could happen if there was a previous error,
|
||||||
|
which would have already been reported. */
|
||||||
|
if (!g_WrkProof.errorCount) bug(2103); /* There must have been an error */
|
||||||
|
goto returnPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bigSubstSchemeVarLen; i++) {
|
||||||
|
substSchemeFrstVarOcc[i] = -1; /* Initialize */
|
||||||
|
/* (varAssLen[], substInstFrstVarOcc[], are
|
||||||
|
all initialized to 0 by nmbrSpace().) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the .tmp field of g_MathToken[]. to hold position of variable in
|
||||||
|
bigSubstSchemeVars for quicker lookup */
|
||||||
|
for (i = 0; i < bigSubstSchemeVarLen; i++) {
|
||||||
|
g_MathToken[bigSubstSchemeVars[i]].tmp = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan bigSubstSchemeAss to get substSchemeFrstVarOcc[] (1st var
|
||||||
|
occurrence) */
|
||||||
|
for (i = 0; i < bigSubstSchemeLen; i++) {
|
||||||
|
if (g_MathToken[bigSubstSchemeAss[i]].tokenType ==
|
||||||
|
(char)var_) {
|
||||||
|
if (substSchemeFrstVarOcc[g_MathToken[bigSubstSchemeAss[
|
||||||
|
i]].tmp] == -1) {
|
||||||
|
substSchemeFrstVarOcc[g_MathToken[bigSubstSchemeAss[
|
||||||
|
i]].tmp] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the scan */
|
||||||
|
v = -1; /* Position in bigSubstSchemeVars */
|
||||||
|
p = 0; /* Position in bigSubstSchemeAss */
|
||||||
|
q = 0; /* Position in bigSubstInstAss */
|
||||||
|
ambiguityCheck: /* Re-entry point to see if unification is unique */
|
||||||
|
while (p != bigSubstSchemeLen-1 || q != bigSubstInstLen-1) {
|
||||||
|
/*E*/if(db7&&v>=0)printLongLine(cat("p ", str((double)p), " q ", str((double)q), " VAR ",str((double)v),
|
||||||
|
/*E*/ " ASSIGNED ", nmbrCvtMToVString(
|
||||||
|
/*E*/ nmbrMid(bigSubstInstAss,substInstFrstVarOcc[v]+1,
|
||||||
|
/*E*/ varAssLen[v])), NULL), "", " ");
|
||||||
|
/*E*/if(db7)nmbrLet(&bigSubstInstAss,bigSubstInstAss);
|
||||||
|
/*E*/if(db7){print2("Enter scan: v=%ld,p=%ld,q=%ld\n",v,p,q); let(&tmpStr,"");}
|
||||||
|
tokenNum = bigSubstSchemeAss[p];
|
||||||
|
if (g_MathToken[tokenNum].tokenType == (char)con_) {
|
||||||
|
/* Constants must match in both substScheme and definiendum assumptions */
|
||||||
|
if (tokenNum == bigSubstInstAss[q]) {
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
/*E*/if(db7)print2(" Exit, c ok: v=%ld,p=%ld,q=%ld\n",v,p,q);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
/* Backtrack to last variable assigned and add 1 to its length */
|
||||||
|
breakFlag = 0;
|
||||||
|
contFlag = 1;
|
||||||
|
while (contFlag) {
|
||||||
|
if (v < 0) {
|
||||||
|
breakFlag = 1;
|
||||||
|
break; /* Error - possibilities exhausted */
|
||||||
|
}
|
||||||
|
varAssLen[v]++;
|
||||||
|
p = substSchemeFrstVarOcc[v] + 1;
|
||||||
|
q = substInstFrstVarOcc[v] + varAssLen[v];
|
||||||
|
contFlag = 0;
|
||||||
|
if (bigSubstInstAss[q-1] == g_mathTokens) {
|
||||||
|
/* It ran into the dummy token separating the assumptions.
|
||||||
|
A variable cannot be assigned this dummy token. Therefore,
|
||||||
|
we must pop back a variable. (This test speeds up
|
||||||
|
the program; theoretically, it is not needed.) */
|
||||||
|
/*E*/if(db7){print2("GOT TO DUMMY TOKEN1\n");}
|
||||||
|
v--;
|
||||||
|
contFlag = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (q >= bigSubstInstLen) {
|
||||||
|
/* It overflowed the end of bigSubstInstAss; pop back a variable */
|
||||||
|
v--;
|
||||||
|
contFlag = 1;
|
||||||
|
bug(2104); /* Should be trapped above */
|
||||||
|
}
|
||||||
|
} /* end while */
|
||||||
|
if (breakFlag) {
|
||||||
|
/*E*/if(db7)print2(" Exit, c bktrk bad: v=%ld,p=%ld,q=%ld\n",v,p,q);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*E*/if(db7)print2(" Exit, c bktrk ok: v=%ld,p=%ld,q=%ld\n",v,p,q);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* It's a variable. If its the first occurrence, init length to 0 */
|
||||||
|
v1 = g_MathToken[tokenNum].tmp;
|
||||||
|
if (v1 > v) {
|
||||||
|
if (v1 != v + 1) bug(2105);
|
||||||
|
v = v1;
|
||||||
|
varAssLen[v] = 0; /* variable length */
|
||||||
|
substInstFrstVarOcc[v] = q; /* variable start in bigSubstInstAss */
|
||||||
|
p++;
|
||||||
|
/*E*/if(db7)print2(" Exit, v new: v=%ld,p=%ld,q=%ld\n",v,p,q);
|
||||||
|
continue;
|
||||||
|
} else { /* It's not the first occurrence; check that it matches */
|
||||||
|
breakFlag = 0;
|
||||||
|
for (i = 0; i < varAssLen[v1]; i++) {
|
||||||
|
if (q + i >= bigSubstInstLen) {
|
||||||
|
/* It overflowed the end of bigSubstInstAss */
|
||||||
|
breakFlag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (bigSubstInstAss[substInstFrstVarOcc[v1] + i] !=
|
||||||
|
bigSubstInstAss[q + i]) {
|
||||||
|
/* The variable assignment mismatched */
|
||||||
|
breakFlag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (breakFlag) {
|
||||||
|
/* Backtrack to last variable assigned and add 1 to its length */
|
||||||
|
breakFlag = 0;
|
||||||
|
contFlag = 1;
|
||||||
|
while (contFlag) {
|
||||||
|
if (v < 0) {
|
||||||
|
breakFlag = 1;
|
||||||
|
break; /* Error - possibilities exhausted */
|
||||||
|
}
|
||||||
|
varAssLen[v]++;
|
||||||
|
p = substSchemeFrstVarOcc[v] + 1;
|
||||||
|
q = substInstFrstVarOcc[v] + varAssLen[v];
|
||||||
|
contFlag = 0;
|
||||||
|
if (bigSubstInstAss[q-1] == g_mathTokens) {
|
||||||
|
/* It ran into the dummy token separating the assumptions.
|
||||||
|
A variable cannot be assigned this dummy token. Therefore,
|
||||||
|
we must pop back a variable. (This test speeds up
|
||||||
|
the program; theoretically, it is not needed.) */
|
||||||
|
/*E*/if(db7)print2("GOT TO DUMMY TOKEN\n");
|
||||||
|
v--;
|
||||||
|
contFlag = 1;
|
||||||
|
continue; /* 24-Sep-2010 nm Added missing trap to fix bug(2106) */
|
||||||
|
}
|
||||||
|
if (q >= bigSubstInstLen) {
|
||||||
|
/* It overflowed the end of bigSubstInstAss; pop back a variable */
|
||||||
|
v--;
|
||||||
|
contFlag = 1;
|
||||||
|
bug(2106); /* Should be trapped above */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (breakFlag) {
|
||||||
|
/*E*/if(db7){print2(" Exit, vold bck bad: v=%ld,p=%ld,q=%ld\n",v,p,q);}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*E*/if(db7)print2(" Exit, vold bck ok: v=%ld,p=%ld,q=%ld\n",v,p,q);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
p++;
|
||||||
|
q = q + varAssLen[v1];
|
||||||
|
/*E*/if(db7)print2(" Exit, vold ok: v=%ld,p=%ld,q=%ld\n",v,p,q);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} /* end if first occurrence */
|
||||||
|
} /* end if constant */
|
||||||
|
} /* end while */
|
||||||
|
|
||||||
|
/*E*/if(db7)printLongLine(cat("BIGVR ", nmbrCvtMToVString(bigSubstSchemeVars),
|
||||||
|
/*E*/ NULL), "", " ");
|
||||||
|
/*E*/if(db7)print2(
|
||||||
|
/*E*/"p=%ld,bigSubstSchemeLen=%ld;q=%ld,bigSubstInstLen=%ld;v=%ld,bigSubstSchemeVarLen=%ld\n",
|
||||||
|
/*E*/ p,bigSubstSchemeLen,q,bigSubstInstLen,v,bigSubstSchemeVarLen);
|
||||||
|
/* See if the assignment completed normally */
|
||||||
|
if (v == -1) {
|
||||||
|
if (ambiguityCheckFlag) {
|
||||||
|
/* This is what we wanted to see -- no further unification possible */
|
||||||
|
goto returnPoint;
|
||||||
|
}
|
||||||
|
if (!g_WrkProof.errorCount) {
|
||||||
|
let(&tmpStr, "");
|
||||||
|
j = g_Statement[substScheme].numReqHyp;
|
||||||
|
for (i = 0; i < j; i++) {
|
||||||
|
k = g_WrkProof.RPNStack[g_WrkProof.RPNStackPtr - j + i]; /* Step */
|
||||||
|
let(&tmpStr2, nmbrCvtMToVString(g_WrkProof.mathStringPtrs[k]));
|
||||||
|
if (tmpStr2[0] == 0) let(&tmpStr2,
|
||||||
|
"? (Unknown step or previous error; unification ignored)");
|
||||||
|
let(&tmpStr, cat(tmpStr, "\n Hypothesis ", str((double)i + 1), ": ",
|
||||||
|
nmbrCvtMToVString(
|
||||||
|
g_Statement[g_Statement[substScheme].reqHypList[i]].mathString),
|
||||||
|
"\n Step ", str((double)k + 1),
|
||||||
|
": ", tmpStr2, NULL));
|
||||||
|
} /* Next i */
|
||||||
|
/* tmpStr = shortDumpRPNStack(); */ /* Old version */
|
||||||
|
sourceError(g_WrkProof.stepSrcPtrPntr[step],
|
||||||
|
g_WrkProof.stepSrcPtrNmbr[step],
|
||||||
|
statementNum, cat(
|
||||||
|
"The hypotheses of statement \"", g_Statement[substScheme].labelName,
|
||||||
|
"\" at proof step ", str((double)step + 1),
|
||||||
|
" cannot be unified.", tmpStr, NULL));
|
||||||
|
/* sourceError(g_WrkProof.stepSrcPtrPntr[step],
|
||||||
|
g_WrkProof.stepSrcPtrNmbr[step],
|
||||||
|
statementNum, cat(
|
||||||
|
"The hypotheses of the statement at proof step ",
|
||||||
|
str(step + 1),
|
||||||
|
" cannot be unified. The statement \"",
|
||||||
|
g_Statement[substScheme].labelName,
|
||||||
|
"\" requires ",
|
||||||
|
str(g_Statement[substScheme].numReqHyp),
|
||||||
|
" hypotheses. The ",tmpStr,
|
||||||
|
". Type \"SHOW PROOF ",g_Statement[statementNum].labelName,
|
||||||
|
"\" to see the proof attempt.",NULL)); */ /* Old version */
|
||||||
|
let(&tmpStr, "");
|
||||||
|
let(&tmpStr2, "");
|
||||||
|
}
|
||||||
|
g_WrkProof.errorCount++;
|
||||||
|
goto returnPoint;
|
||||||
|
}
|
||||||
|
if (p != bigSubstSchemeLen - 1 || q != bigSubstInstLen - 1
|
||||||
|
|| v != bigSubstSchemeVarLen - 1) bug(2107);
|
||||||
|
|
||||||
|
/* If a second unification was possible, save the first result for the
|
||||||
|
error message */
|
||||||
|
if (ambiguityCheckFlag) {
|
||||||
|
if (unkHypFlag) {
|
||||||
|
/* If a hypothesis was unknown, the fact that the unification is ambiguous
|
||||||
|
doesn't matter, so just return with an empty (unknown) answer. */
|
||||||
|
nmbrLet(&result,NULL_NMBRSTRING);
|
||||||
|
goto returnPoint;
|
||||||
|
}
|
||||||
|
nmbrLet(&saveResult, result);
|
||||||
|
nmbrLet(&result, NULL_NMBRSTRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** Get step information if requested *****/
|
||||||
|
if (!ambiguityCheckFlag) { /* This is the real (first) unification */
|
||||||
|
if (getStep.stepNum) {
|
||||||
|
/* See if this step is the requested step; if so get source substitutions */
|
||||||
|
if (step + 1 == getStep.stepNum) {
|
||||||
|
nmbrLet(&getStep.sourceSubstsNmbr, nmbrExtractVars(
|
||||||
|
g_Statement[substScheme].mathString));
|
||||||
|
k = nmbrLen(getStep.sourceSubstsNmbr);
|
||||||
|
pntrLet(&getStep.sourceSubstsPntr,
|
||||||
|
pntrNSpace(k));
|
||||||
|
for (m = 0; m < k; m++) {
|
||||||
|
pos = g_MathToken[getStep.sourceSubstsNmbr[m]].tmp; /* Subst pos */
|
||||||
|
nmbrLet((nmbrString **)(&getStep.sourceSubstsPntr[m]),
|
||||||
|
nmbrMid(bigSubstInstAss,
|
||||||
|
substInstFrstVarOcc[pos] + 1, /* Subst pos */
|
||||||
|
varAssLen[pos]) /* Subst length */ );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* See if this step is a target hyp; if so get target substitutions */
|
||||||
|
j = 0;
|
||||||
|
numReqHyp = g_Statement[substScheme].numReqHyp;
|
||||||
|
nmbrHypPtr = g_Statement[substScheme].reqHypList;
|
||||||
|
for (i = g_WrkProof.RPNStackPtr - numReqHyp; i < g_WrkProof.RPNStackPtr; i++) {
|
||||||
|
if (g_WrkProof.RPNStack[i] == getStep.stepNum - 1) {
|
||||||
|
/* This is parent of target; get hyp's variable substitutions */
|
||||||
|
nmbrLet(&getStep.targetSubstsNmbr, nmbrExtractVars(
|
||||||
|
g_Statement[nmbrHypPtr[j]].mathString));
|
||||||
|
k = nmbrLen(getStep.targetSubstsNmbr);
|
||||||
|
pntrLet(&getStep.targetSubstsPntr, pntrNSpace(k));
|
||||||
|
for (m = 0; m < k; m++) {
|
||||||
|
pos = g_MathToken[getStep.targetSubstsNmbr[m]].tmp;
|
||||||
|
/* Substitution position */
|
||||||
|
nmbrLet((nmbrString **)(&getStep.targetSubstsPntr[m]),
|
||||||
|
nmbrMid(bigSubstInstAss,
|
||||||
|
substInstFrstVarOcc[pos] + 1, /* Subst pos */
|
||||||
|
varAssLen[pos]) /* Subst length */ );
|
||||||
|
} /* Next m */
|
||||||
|
} /* End if (g_WrkProof.RPNStack[i] == getStep.stepNum - 1) */
|
||||||
|
j++;
|
||||||
|
} /* Next i */
|
||||||
|
} /* End if (getStep.stepNum) */
|
||||||
|
} /* End if (!ambiguityCheckFlag) */
|
||||||
|
/***** End of getting step information *****/
|
||||||
|
|
||||||
|
|
||||||
|
/***** Check for $d violations *****/
|
||||||
|
if (!ambiguityCheckFlag) { /* This is the real (first) unification */
|
||||||
|
nmbrTmpPtrAS = g_Statement[substScheme].reqDisjVarsA;
|
||||||
|
nmbrTmpPtrBS = g_Statement[substScheme].reqDisjVarsB;
|
||||||
|
dLen = nmbrLen(nmbrTmpPtrAS); /* Number of disjoint variable pairs */
|
||||||
|
if (dLen) { /* There is a disjoint variable requirement */
|
||||||
|
/* (Speedup) Save pointers and lengths for statement being proved */
|
||||||
|
nmbrTmpPtrAIR = g_Statement[statementNum].reqDisjVarsA;
|
||||||
|
nmbrTmpPtrBIR = g_Statement[statementNum].reqDisjVarsB;
|
||||||
|
dILenR = nmbrLen(nmbrTmpPtrAIR); /* Number of disj hypotheses */
|
||||||
|
nmbrTmpPtrAIO = g_Statement[statementNum].optDisjVarsA;
|
||||||
|
nmbrTmpPtrBIO = g_Statement[statementNum].optDisjVarsB;
|
||||||
|
dILenO = nmbrLen(nmbrTmpPtrAIO); /* Number of disj hypotheses */
|
||||||
|
}
|
||||||
|
for (pos = 0; pos < dLen; pos++) { /* Scan the disj var pairs */
|
||||||
|
substAPos = g_MathToken[nmbrTmpPtrAS[pos]].tmp;
|
||||||
|
substALen = varAssLen[substAPos];
|
||||||
|
instAPos = substInstFrstVarOcc[substAPos];
|
||||||
|
substBPos = g_MathToken[nmbrTmpPtrBS[pos]].tmp;
|
||||||
|
substBLen = varAssLen[substBPos];
|
||||||
|
instBPos = substInstFrstVarOcc[substBPos];
|
||||||
|
for (a = 0; a < substALen; a++) { /* Scan subst of 1st var in disj pair */
|
||||||
|
aToken = bigSubstInstAss[instAPos + a];
|
||||||
|
if (g_MathToken[aToken].tokenType == (char)con_) continue; /* Ignore */
|
||||||
|
|
||||||
|
/* Speed up: find the 1st occurrence of aToken in the disjoint variable
|
||||||
|
list of the statement being proved. */
|
||||||
|
/* To bypass speedup, we would do this:
|
||||||
|
reqStart = 0;
|
||||||
|
optStart = 0; */
|
||||||
|
/* First, see if the variable is in the required list. */
|
||||||
|
foundFlag = 0;
|
||||||
|
for (i = 0; i < dILenR; i++) {
|
||||||
|
if (nmbrTmpPtrAIR[i] == aToken
|
||||||
|
|| nmbrTmpPtrBIR[i] == aToken) {
|
||||||
|
foundFlag = 1;
|
||||||
|
reqStart = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If not, see if it is in the optional list. */
|
||||||
|
if (!foundFlag) {
|
||||||
|
reqStart = dILenR; /* Force skipping required scan */
|
||||||
|
foundFlag = 0;
|
||||||
|
for (i = 0; i < dILenO; i++) {
|
||||||
|
if (nmbrTmpPtrAIO[i] == aToken
|
||||||
|
|| nmbrTmpPtrBIO[i] == aToken) {
|
||||||
|
foundFlag = 1;
|
||||||
|
optStart = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundFlag) optStart = dILenO; /* Force skipping optional scan */
|
||||||
|
} else {
|
||||||
|
optStart = 0;
|
||||||
|
} /* (End if (!foundFlag)) */
|
||||||
|
/* (End of speedup section) */
|
||||||
|
|
||||||
|
for (b = 0; b < substBLen; b++) { /* Scan subst of 2nd var in pair */
|
||||||
|
bToken = bigSubstInstAss[instBPos + b];
|
||||||
|
if (g_MathToken[bToken].tokenType == (char)con_) continue; /* Ignore */
|
||||||
|
if (aToken == bToken) {
|
||||||
|
if (!g_WrkProof.errorCount) { /* No previous errors in this proof */
|
||||||
|
sourceError(g_WrkProof.stepSrcPtrPntr[step], /* source ptr */
|
||||||
|
g_WrkProof.stepSrcPtrNmbr[step], /* size of token */
|
||||||
|
statementNum, cat(
|
||||||
|
"There is a disjoint variable ($d) violation at proof step ",
|
||||||
|
str((double)step + 1),". Assertion \"",
|
||||||
|
g_Statement[substScheme].labelName,
|
||||||
|
"\" requires that variables \"",
|
||||||
|
g_MathToken[nmbrTmpPtrAS[pos]].tokenName,
|
||||||
|
"\" and \"",
|
||||||
|
g_MathToken[nmbrTmpPtrBS[pos]].tokenName,
|
||||||
|
"\" be disjoint. But \"",
|
||||||
|
g_MathToken[nmbrTmpPtrAS[pos]].tokenName,
|
||||||
|
"\" was substituted with \"",
|
||||||
|
nmbrCvtMToVString(nmbrMid(bigSubstInstAss,instAPos + 1,
|
||||||
|
substALen)),
|
||||||
|
"\" and \"",
|
||||||
|
g_MathToken[nmbrTmpPtrBS[pos]].tokenName,
|
||||||
|
"\" was substituted with \"",
|
||||||
|
nmbrCvtMToVString(nmbrMid(bigSubstInstAss,instBPos + 1,
|
||||||
|
substBLen)),
|
||||||
|
"\". These substitutions have variable \"",
|
||||||
|
g_MathToken[aToken].tokenName,
|
||||||
|
"\" in common.",
|
||||||
|
NULL));
|
||||||
|
let(&tmpStr, ""); /* Force tmp string stack dealloc */
|
||||||
|
nmbrLet(&nmbrTmp,NULL_NMBRSTRING); /* Force tmp stack dealloc */
|
||||||
|
} /* (End if (!g_WrkProof.errorCount) ) */
|
||||||
|
} else { /* aToken != bToken */
|
||||||
|
/* The variables are different. We're still not done though: We
|
||||||
|
must make sure that the $d's of the statement being proved
|
||||||
|
guarantee that they will be disjoint. */
|
||||||
|
/*???Future: use bsearch for speedup? Must modify main READ
|
||||||
|
parsing to produce sorted disj var lists; this would slow down
|
||||||
|
the main READ. */
|
||||||
|
/* Make sure that the variables are in the right order for lookup.*/
|
||||||
|
if (aToken > bToken) {
|
||||||
|
aToken2 = bToken;
|
||||||
|
bToken2 = aToken;
|
||||||
|
} else {
|
||||||
|
aToken2 = aToken;
|
||||||
|
bToken2 = bToken;
|
||||||
|
}
|
||||||
|
/* Scan the required disjoint variable hypotheses to see if they're
|
||||||
|
in it. */
|
||||||
|
/* First, see if both variables are in the required list. */
|
||||||
|
foundFlag = 0;
|
||||||
|
for (i = reqStart; i < dILenR; i++) {
|
||||||
|
if (nmbrTmpPtrAIR[i] == aToken2) {
|
||||||
|
if (nmbrTmpPtrBIR[i] == bToken2) {
|
||||||
|
foundFlag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If not, see if they are in the optional list. */
|
||||||
|
if (!foundFlag) {
|
||||||
|
foundFlag = 0;
|
||||||
|
for (i = optStart; i < dILenO; i++) {
|
||||||
|
if (nmbrTmpPtrAIO[i] == aToken2) {
|
||||||
|
if (nmbrTmpPtrBIO[i] == bToken2) {
|
||||||
|
foundFlag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* (End if (!foundFlag)) */
|
||||||
|
/* If they were in neither place, we have a violation. */
|
||||||
|
if (!foundFlag) {
|
||||||
|
if (!g_WrkProof.errorCount) { /* No previous errors in this proof */
|
||||||
|
sourceError(g_WrkProof.stepSrcPtrPntr[step], /* source */
|
||||||
|
g_WrkProof.stepSrcPtrNmbr[step], /* size of token */
|
||||||
|
statementNum, cat(
|
||||||
|
"There is a disjoint variable ($d) violation at proof step ",
|
||||||
|
str((double)step + 1), ". Assertion \"",
|
||||||
|
g_Statement[substScheme].labelName,
|
||||||
|
"\" requires that variables \"",
|
||||||
|
g_MathToken[nmbrTmpPtrAS[pos]].tokenName,
|
||||||
|
"\" and \"",
|
||||||
|
g_MathToken[nmbrTmpPtrBS[pos]].tokenName,
|
||||||
|
"\" be disjoint. But \"",
|
||||||
|
g_MathToken[nmbrTmpPtrAS[pos]].tokenName,
|
||||||
|
"\" was substituted with \"",
|
||||||
|
nmbrCvtMToVString(nmbrMid(bigSubstInstAss, instAPos + 1,
|
||||||
|
substALen)),
|
||||||
|
"\" and \"",
|
||||||
|
g_MathToken[nmbrTmpPtrBS[pos]].tokenName,
|
||||||
|
"\" was substituted with \"",
|
||||||
|
nmbrCvtMToVString(nmbrMid(bigSubstInstAss, instBPos + 1,
|
||||||
|
substBLen)),
|
||||||
|
"\".", NULL));
|
||||||
|
/* Put missing $d requirement in new line so grep can find
|
||||||
|
them easily in log file */
|
||||||
|
printLongLine(cat("Variables \"",
|
||||||
|
/* 30-Apr-04 nm Put in alphabetic order for easier use if
|
||||||
|
user sorts the list of errors */
|
||||||
|
/* strcmp returns <0 if 1st<2nd */
|
||||||
|
(strcmp(g_MathToken[aToken].tokenName,
|
||||||
|
g_MathToken[bToken].tokenName) < 0)
|
||||||
|
? g_MathToken[aToken].tokenName
|
||||||
|
: g_MathToken[bToken].tokenName,
|
||||||
|
"\" and \"",
|
||||||
|
(strcmp(g_MathToken[aToken].tokenName,
|
||||||
|
g_MathToken[bToken].tokenName) < 0)
|
||||||
|
? g_MathToken[bToken].tokenName
|
||||||
|
: g_MathToken[aToken].tokenName,
|
||||||
|
"\" do not have a disjoint variable requirement in the ",
|
||||||
|
"assertion being proved, \"",
|
||||||
|
g_Statement[statementNum].labelName,
|
||||||
|
"\".", NULL), "", " ");
|
||||||
|
let(&tmpStr, ""); /* Force tmp string stack dealloc */
|
||||||
|
nmbrLet(&nmbrTmp,NULL_NMBRSTRING); /* Force tmp stack dealloc */
|
||||||
|
} /* (End if (!g_WrkProof.errorCount) ) */
|
||||||
|
} /* (End if (!foundFlag)) */
|
||||||
|
} /* (End if (aToken == bToken)) */
|
||||||
|
} /* (Next b) */
|
||||||
|
} /* (Next a) */
|
||||||
|
} /* (Next pos) */
|
||||||
|
} /* (End if (!ambiguityCheck)) */
|
||||||
|
/***** (End of $d violation check) *****/
|
||||||
|
|
||||||
|
/* Assemble the final result */
|
||||||
|
substSchemeLen = nmbrLen(g_Statement[substScheme].mathString);
|
||||||
|
/* Calculate the length of the final result */
|
||||||
|
q = 0;
|
||||||
|
for (p = 0; p < substSchemeLen; p++) {
|
||||||
|
tokenNum = g_Statement[substScheme].mathString[p];
|
||||||
|
if (g_MathToken[tokenNum].tokenType == (char)con_) {
|
||||||
|
q++;
|
||||||
|
} else {
|
||||||
|
q = q + varAssLen[g_MathToken[tokenNum].tmp];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Allocate space for the final result */
|
||||||
|
resultLen = q;
|
||||||
|
nmbrLet(&result,nmbrSpace(resultLen));
|
||||||
|
/* Assign the final result */
|
||||||
|
q = 0;
|
||||||
|
for (p = 0; p < substSchemeLen; p++) {
|
||||||
|
tokenNum = g_Statement[substScheme].mathString[p];
|
||||||
|
if (g_MathToken[tokenNum].tokenType == (char)con_) {
|
||||||
|
result[q] = tokenNum;
|
||||||
|
q++;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < varAssLen[g_MathToken[tokenNum].tmp]; i++){
|
||||||
|
result[q + i] = bigSubstInstAss[i +
|
||||||
|
substInstFrstVarOcc[g_MathToken[tokenNum].tmp]];
|
||||||
|
}
|
||||||
|
q = q + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*E*/if(db7)printLongLine(cat("result ", nmbrCvtMToVString(result), NULL),""," ");
|
||||||
|
|
||||||
|
if (ambiguityCheckFlag) {
|
||||||
|
if (!g_WrkProof.errorCount) {
|
||||||
|
/*??? Make sure suggested commands are correct. */
|
||||||
|
sourceError(g_WrkProof.stepSrcPtrPntr[step],
|
||||||
|
g_WrkProof.stepSrcPtrNmbr[step],
|
||||||
|
statementNum, cat(
|
||||||
|
"The unification with the hypotheses of the statement at proof step ",
|
||||||
|
str((double)step + 1),
|
||||||
|
" is not unique. Two possible results at this step are \"",
|
||||||
|
nmbrCvtMToVString(saveResult),
|
||||||
|
"\" and \"",nmbrCvtMToVString(result),
|
||||||
|
"\". Type \"SHOW PROOF ",g_Statement[statementNum].labelName,
|
||||||
|
"\" to see the proof attempt.",NULL));
|
||||||
|
}
|
||||||
|
g_WrkProof.errorCount++;
|
||||||
|
goto returnPoint;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Prepare to see if the unification is unique */
|
||||||
|
while (1) {
|
||||||
|
v--;
|
||||||
|
if (v < 0) {
|
||||||
|
goto returnPoint; /* It's unique */
|
||||||
|
}
|
||||||
|
varAssLen[v]++;
|
||||||
|
p = substSchemeFrstVarOcc[v] + 1;
|
||||||
|
q = substInstFrstVarOcc[v] + varAssLen[v];
|
||||||
|
if (bigSubstInstAss[q - 1] != g_mathTokens) break;
|
||||||
|
if (q >= bigSubstInstLen) bug(2110);
|
||||||
|
}
|
||||||
|
ambiguityCheckFlag = 1;
|
||||||
|
goto ambiguityCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
returnPoint:
|
||||||
|
|
||||||
|
/* Free up all allocated nmbrString space */
|
||||||
|
for (i = 0; i < bigSubstSchemeVarLen; i++) {
|
||||||
|
/* Make the data-holding structures legal nmbrStrings before nmbrLet() */
|
||||||
|
/*???Make more efficient by deallocating directly*/
|
||||||
|
substSchemeFrstVarOcc[i] = 0;
|
||||||
|
varAssLen[i] = 0;
|
||||||
|
substInstFrstVarOcc[i] = 0;
|
||||||
|
}
|
||||||
|
nmbrLet(&bigSubstSchemeVars,NULL_NMBRSTRING);
|
||||||
|
nmbrLet(&substSchemeFrstVarOcc,NULL_NMBRSTRING);
|
||||||
|
nmbrLet(&varAssLen,NULL_NMBRSTRING);
|
||||||
|
nmbrLet(&substInstFrstVarOcc,NULL_NMBRSTRING);
|
||||||
|
nmbrLet(&saveResult,NULL_NMBRSTRING);
|
||||||
|
|
||||||
|
g_nmbrStartTempAllocStack = nmbrSaveTempAllocStack;
|
||||||
|
return(result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Deallocate the math symbol strings assigned in wrkProof structure during
|
||||||
|
proof verification. This should be called after verifyProof() and after the
|
||||||
|
math symbol strings have been used for proof printouts, etc. */
|
||||||
|
/* Note that this does NOT free the other allocations in g_WrkProof. The
|
||||||
|
ERASE command will do this. */
|
||||||
|
void cleanWrkProof(void) {
|
||||||
|
|
||||||
|
long step;
|
||||||
|
char type;
|
||||||
|
|
||||||
|
for (step = 0; step < g_WrkProof.numSteps; step++) {
|
||||||
|
if (g_WrkProof.proofString[step] > 0) {
|
||||||
|
type = g_Statement[g_WrkProof.proofString[step]].type;
|
||||||
|
if (type == a_ || type == p_) {
|
||||||
|
/* Allocation was only done if: (1) it's not a local label reference
|
||||||
|
and (2) it's not a hypothesis. In this case, deallocate. */
|
||||||
|
nmbrLet((nmbrString **)(&g_WrkProof.mathStringPtrs[step]),
|
||||||
|
NULL_NMBRSTRING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
mmveri.h
Normal file
45
mmveri.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2005 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMVERI_H_
|
||||||
|
#define METAMATH_MMVERI_H_
|
||||||
|
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
char verifyProof(long statemNum);
|
||||||
|
|
||||||
|
/* assignVar() finds an assignment to substScheme variables that match
|
||||||
|
the assumptions specified in the reason string */
|
||||||
|
nmbrString *assignVar(nmbrString *bigSubstSchemeAss,
|
||||||
|
nmbrString *bigSubstInstAss, long substScheme,
|
||||||
|
/* For error messages: */
|
||||||
|
long statementNum, long step, flag unkHypFlag);
|
||||||
|
|
||||||
|
/* Deallocate the math symbol strings assigned in g_WrkProof structure during
|
||||||
|
proof verification. This should be called after verifyProof() and after the
|
||||||
|
math symbol strings have been used for proof printouts, etc. */
|
||||||
|
/* Note that this does NOT free the other allocations in g_WrkProof. The
|
||||||
|
ERASE command will do this. */
|
||||||
|
void cleanWrkProof(void);
|
||||||
|
|
||||||
|
/* Structure for getting info about a step for SHOW PROOF/STEP command */
|
||||||
|
/* If getStep.stepNum is nonzero, we should get info about that step. */
|
||||||
|
/* This structure should be deallocated after use. */
|
||||||
|
struct getStep_struct {
|
||||||
|
long stepNum; /* Step # to get info about */
|
||||||
|
long sourceStmt; /* Right side of = in proof display */
|
||||||
|
long targetStmt; /* Left side of = in proof display */
|
||||||
|
long targetParentStep; /* Step # of target's parent */
|
||||||
|
long targetParentStmt; /* Statement # of target's parent */
|
||||||
|
nmbrString *sourceHyps; /* List of step #'s */
|
||||||
|
nmbrString *sourceSubstsNmbr; /* List of vars w/ ptr to subst math tokens */
|
||||||
|
pntrString *sourceSubstsPntr; /* List of vars w/ ptr to subst math tokens */
|
||||||
|
nmbrString *targetSubstsNmbr; /* List of vars w/ ptr to subst math tokens */
|
||||||
|
pntrString *targetSubstsPntr; /* List of vars w/ ptr to subst math tokens */
|
||||||
|
};
|
||||||
|
extern struct getStep_struct getStep;
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMVERI_H_ */
|
997
mmvstr.c
Normal file
997
mmvstr.c
Normal file
@ -0,0 +1,997 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2019 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
mmvstr.c - VMS-BASIC variable length string library routines header
|
||||||
|
This is an emulation of the string functions available in VMS BASIC.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*** See the comments in mmvstr.h for an explanation of these functions ******/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "mmvstr.h"
|
||||||
|
/*E*/ /*Next line is need to declare "db" for debugging*/
|
||||||
|
#include "mmdata.h"
|
||||||
|
/* 1-Dec-05 nm
|
||||||
|
mmdata.h is also used to declare the bug() function that is called in
|
||||||
|
several places by mmvstr.c. To make mmvstr.c and mmvstr.h completely
|
||||||
|
independent of the other programs, for use with another project, do the
|
||||||
|
following:
|
||||||
|
(1) Remove all lines beginning with the "/ *E* /" comment.
|
||||||
|
(2) Remove all calls to the bug() function (4 places).
|
||||||
|
To see an example of stand-alone usage of the mmvstr.c functions, see
|
||||||
|
the program lattice.c and several others included in
|
||||||
|
http://us.metamath.org/downloads/quantum-logic.tar.gz
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*E*/long db1=0;
|
||||||
|
#ifdef NDEBUG
|
||||||
|
# define INCDB1(x)
|
||||||
|
#else
|
||||||
|
# define INCDB1(x) db1 += (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_ALLOC_STACK 100
|
||||||
|
long g_tempAllocStackTop = 0; /* Top of stack for tempAlloc functon */
|
||||||
|
long g_startTempAllocStack = 0; /* Where to start freeing temporary allocation
|
||||||
|
when let() is called (normally 0, except in
|
||||||
|
special nested vstring functions) */
|
||||||
|
void *tempAllocStack[MAX_ALLOC_STACK];
|
||||||
|
|
||||||
|
static void freeTempAlloc(void)
|
||||||
|
{
|
||||||
|
/* All memory previously allocated with tempAlloc is deallocated. */
|
||||||
|
/* EXCEPT: When g_startTempAllocStack != 0, the freeing will start at
|
||||||
|
g_startTempAllocStack. */
|
||||||
|
long i;
|
||||||
|
for (i = g_startTempAllocStack; i < g_tempAllocStackTop; i++) {
|
||||||
|
/*E*/INCDB1(-1 - (long)strlen(tempAllocStack[i]));
|
||||||
|
/*E* /printf("%ld removing [%s]\n", db1, tempAllocStack[i]);*/
|
||||||
|
free(tempAllocStack[i]);
|
||||||
|
}
|
||||||
|
g_tempAllocStackTop = g_startTempAllocStack;
|
||||||
|
} /* freeTempAlloc */
|
||||||
|
|
||||||
|
|
||||||
|
static void pushTempAlloc(void *mem)
|
||||||
|
{
|
||||||
|
if (g_tempAllocStackTop >= (MAX_ALLOC_STACK-1)) {
|
||||||
|
printf("*** FATAL ERROR *** Temporary string stack overflow\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
bug(2201);
|
||||||
|
}
|
||||||
|
tempAllocStack[g_tempAllocStackTop++] = mem;
|
||||||
|
} /* pushTempAlloc */
|
||||||
|
|
||||||
|
|
||||||
|
static void* tempAlloc(long size) /* String memory allocation/deallocation */
|
||||||
|
{
|
||||||
|
void* memptr = malloc((size_t)size);
|
||||||
|
if (!memptr || size == 0) {
|
||||||
|
printf("*** FATAL ERROR *** Temporary string allocation failed\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
bug(2202);
|
||||||
|
}
|
||||||
|
pushTempAlloc(memptr);
|
||||||
|
/*E*/INCDB1(size);
|
||||||
|
/*E* /printf("%ld adding\n",db1);*/
|
||||||
|
return memptr;
|
||||||
|
} /* tempAlloc */
|
||||||
|
|
||||||
|
|
||||||
|
/* Make string have temporary allocation to be released by next let() */
|
||||||
|
/* Warning: after makeTempAlloc() is called, the vstring may NOT be
|
||||||
|
assigned again with let() */
|
||||||
|
void makeTempAlloc(vstring s)
|
||||||
|
{
|
||||||
|
pushTempAlloc(s);
|
||||||
|
/*E*/INCDB1((long)strlen(s) + 1);
|
||||||
|
/*E*/db-=(long)strlen(s) + 1;
|
||||||
|
/*E* /printf("%ld temping[%s]\n", db1, s);*/
|
||||||
|
} /* makeTempAlloc */
|
||||||
|
|
||||||
|
|
||||||
|
/* 8-Jul-2013 Wolf Lammen - rewritten to simplify it */
|
||||||
|
void let(vstring *target, vstring source) /* String assignment */
|
||||||
|
/* This function must ALWAYS be called to make assignment to */
|
||||||
|
/* a vstring in order for the memory cleanup routines, etc. */
|
||||||
|
/* to work properly. If a vstring has never been assigned before, */
|
||||||
|
/* it is the user's responsibility to initialize it to "" (the */
|
||||||
|
/* null string). */
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t sourceLength = strlen(source); /* Save its length */
|
||||||
|
size_t targetLength = strlen(*target); /* Save its length */
|
||||||
|
/*E*/if (targetLength) {
|
||||||
|
/*E*/ db -= (long)targetLength+1;
|
||||||
|
/*E*/ /* printf("%ld Deleting %s\n",db,*target); */
|
||||||
|
/*E*/}
|
||||||
|
/*E*/if (sourceLength) {
|
||||||
|
/*E*/ db += (long)sourceLength+1;
|
||||||
|
/*E*/ /* printf("%ld Adding %s\n",db,source); */
|
||||||
|
/*E*/}
|
||||||
|
if (targetLength < sourceLength) { /* Old string has not enough room for new one */
|
||||||
|
/* Free old string space and allocate new space */
|
||||||
|
if (targetLength)
|
||||||
|
free(*target); /* Free old space */
|
||||||
|
*target = malloc(sourceLength + 1); /* Allocate new space */
|
||||||
|
if (!*target) {
|
||||||
|
printf("*** FATAL ERROR *** String memory couldn't be allocated\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
bug(2204);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceLength) {
|
||||||
|
strcpy(*target, source);
|
||||||
|
} else {
|
||||||
|
/* Empty strings could still be temporaries, so always assign a constant */
|
||||||
|
if (targetLength) {
|
||||||
|
free(*target);
|
||||||
|
}
|
||||||
|
*target= "";
|
||||||
|
}
|
||||||
|
|
||||||
|
freeTempAlloc(); /* Free up temporary strings used in expression computation */
|
||||||
|
|
||||||
|
} /* let */
|
||||||
|
|
||||||
|
vstring cat(vstring string1,...) /* String concatenation */
|
||||||
|
#define MAX_CAT_ARGS 50
|
||||||
|
{
|
||||||
|
va_list ap; /* Declare list incrementer */
|
||||||
|
vstring arg[MAX_CAT_ARGS]; /* Array to store arguments */
|
||||||
|
size_t argPos[MAX_CAT_ARGS]; /* Array of argument positions in result */
|
||||||
|
vstring result;
|
||||||
|
int i;
|
||||||
|
int numArgs = 0; /* Define "last argument" */
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
char* curArg = string1;
|
||||||
|
|
||||||
|
va_start(ap, string1); /* Begin the session */
|
||||||
|
do {
|
||||||
|
/* User-provided argument list must terminate with 0 */
|
||||||
|
if (numArgs >= MAX_CAT_ARGS) {
|
||||||
|
printf("*** FATAL ERROR *** Too many cat() arguments\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
bug(2206);
|
||||||
|
}
|
||||||
|
arg[numArgs] = curArg;
|
||||||
|
argPos[numArgs] = pos;
|
||||||
|
pos += strlen(curArg);
|
||||||
|
} while (++numArgs, (curArg = va_arg(ap,char *)) != 0);
|
||||||
|
va_end(ap); /* End var args session */
|
||||||
|
|
||||||
|
/* Allocate the memory for it */
|
||||||
|
result = tempAlloc((long)pos+1);
|
||||||
|
/* Move the strings into the newly allocated area */
|
||||||
|
for (i = 0; i < numArgs; ++i)
|
||||||
|
strcpy(result + argPos[i], arg[i]);
|
||||||
|
return result;
|
||||||
|
} /* cat */
|
||||||
|
|
||||||
|
|
||||||
|
/* 20-Oct-2013 Wolf Lammen - allow unlimited input line lengths */
|
||||||
|
/* Input a line from the user or from a file */
|
||||||
|
/* Returns 1 if a (possibly empty) line was successfully read, 0 if EOF */
|
||||||
|
int linput(FILE *stream, const char* ask, vstring *target)
|
||||||
|
{ /* Note: "vstring *target" means "char **target" */
|
||||||
|
/*
|
||||||
|
BASIC: linput "what"; a$
|
||||||
|
c: linput(NULL, "what?", &a);
|
||||||
|
|
||||||
|
BASIC: linput #1, a$ (error trap on EOF)
|
||||||
|
c: if (!linput(file1, NULL, &a)) break; (break on EOF)
|
||||||
|
|
||||||
|
*/
|
||||||
|
/* This function prints a prompt (if 'ask' is not NULL), gets a line from
|
||||||
|
the stream, and assigns it to target using the let(&...) function.
|
||||||
|
0 is returned when end-of-file is encountered. The vstring
|
||||||
|
*target MUST be initialized to "" or previously assigned by let(&...)
|
||||||
|
before using it in linput. */
|
||||||
|
char f[10001]; /* Read in chunks up to 10000 characters */
|
||||||
|
int result = 0;
|
||||||
|
int eol_found = 0;
|
||||||
|
if (ask) {
|
||||||
|
printf("%s", ask);
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (stream == NULL) stream = stdin;
|
||||||
|
while (!eol_found && fgets(f, sizeof(f), stream))
|
||||||
|
{
|
||||||
|
size_t endpos = strlen(f) - 1;
|
||||||
|
eol_found = (f[endpos] == '\n');
|
||||||
|
/* If the last line in the file has no newline, eol_found will be 0 here.
|
||||||
|
The fgets() above will return 0 and prevent another loop iteration. */
|
||||||
|
if (eol_found)
|
||||||
|
f[endpos] = 0; /* The return string will have any newline stripped. */
|
||||||
|
if (result)
|
||||||
|
/* Append additional parts of the line to *target */
|
||||||
|
/* The let() reallocates *target and copies the concatenation of the
|
||||||
|
old *target and the additional input f[] to it */
|
||||||
|
let(target /* = &(*target) */, cat(*target, f, NULL));
|
||||||
|
else
|
||||||
|
/* This is the first time through the loop, and normally
|
||||||
|
the only one unless the input line overflows f[] */
|
||||||
|
let(target, f); /* Allocate *target and copy f to it */
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} /* linput */
|
||||||
|
|
||||||
|
|
||||||
|
/* Find out the length of a string */
|
||||||
|
long len(vstring s)
|
||||||
|
{
|
||||||
|
return ((long)strlen(s));
|
||||||
|
} /* len */
|
||||||
|
|
||||||
|
|
||||||
|
/* Extract sin from character position start to stop into sout */
|
||||||
|
vstring seg(vstring sin, long start, long stop)
|
||||||
|
{
|
||||||
|
if (start < 1) start = 1;
|
||||||
|
return mid(sin, start, stop - start + 1);
|
||||||
|
} /* seg */
|
||||||
|
|
||||||
|
|
||||||
|
/* Extract sin from character position start for length len */
|
||||||
|
vstring mid(vstring sin, long start, long length)
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
if (start < 1) start = 1;
|
||||||
|
if (length < 0) length = 0;
|
||||||
|
sout=tempAlloc(length + 1);
|
||||||
|
strncpy(sout,sin + start - 1, (size_t)length);
|
||||||
|
/*E*/ /*??? Should db be subtracted from if length > end of string? */
|
||||||
|
sout[length] = 0;
|
||||||
|
return (sout);
|
||||||
|
} /* mid */
|
||||||
|
|
||||||
|
|
||||||
|
/* Extract leftmost n characters */
|
||||||
|
vstring left(vstring sin,long n)
|
||||||
|
{
|
||||||
|
return mid(sin, 1, n);
|
||||||
|
} /* left */
|
||||||
|
|
||||||
|
|
||||||
|
/* Extract after character n */
|
||||||
|
vstring right(vstring sin, long n)
|
||||||
|
{
|
||||||
|
return seg(sin, n, (long)(strlen(sin)));
|
||||||
|
} /* right */
|
||||||
|
|
||||||
|
|
||||||
|
/* Emulate VMS BASIC edit$ command */
|
||||||
|
vstring edit(vstring sin,long control)
|
||||||
|
#define isblank_(c) ((c == ' ') || (c == '\t'))
|
||||||
|
/* 11-Sep-2009 nm Added _ to fix '"isblank" redefined' compiler warning */
|
||||||
|
#define isblankorlf_(c) ((c == ' ') || (c == '\t') || (c == '\n'))
|
||||||
|
/* 8-May-2015 nm added isblankorlf_ */
|
||||||
|
{
|
||||||
|
/* EDIT$ (from VMS BASIC manual)
|
||||||
|
Syntax: str-vbl = EDIT$(str-exp, int-exp)
|
||||||
|
Values Effect
|
||||||
|
1 Trim parity bits
|
||||||
|
2 Discard all spaces and tabs
|
||||||
|
4 Discard characters: CR, LF, FF, ESC, RUBOUT, and NULL
|
||||||
|
8 Discard leading spaces and tabs
|
||||||
|
16 Reduce spaces and tabs to one space
|
||||||
|
32 Convert lowercase to uppercase
|
||||||
|
64 Convert [ to ( and ] to )
|
||||||
|
128 Discard trailing spaces and tabs
|
||||||
|
256 Do not alter characters inside quotes
|
||||||
|
|
||||||
|
(non-BASIC extensions)
|
||||||
|
512 Convert uppercase to lowercase
|
||||||
|
1024 Tab the line (convert spaces to equivalent tabs)
|
||||||
|
2048 Untab the line (convert tabs to equivalent spaces)
|
||||||
|
4096 Convert VT220 screen print frame graphics to -,|,+ characters
|
||||||
|
|
||||||
|
(Added 10/24/03:)
|
||||||
|
8192 Discard CR only (to assist DOS-to-Unix conversion)
|
||||||
|
|
||||||
|
(Added 8-May-2015 nm:)
|
||||||
|
16384 Discard trailing spaces, tabs, and LFs
|
||||||
|
*/
|
||||||
|
vstring sout;
|
||||||
|
long i, j, k, m;
|
||||||
|
int last_char_is_blank;
|
||||||
|
int trim_flag, discardctrl_flag, bracket_flag, quote_flag, case_flag;
|
||||||
|
int alldiscard_flag, leaddiscard_flag, traildiscard_flag,
|
||||||
|
traildiscardLF_flag, reduce_flag;
|
||||||
|
int processing_inside_quote=0;
|
||||||
|
int lowercase_flag, tab_flag, untab_flag, screen_flag, discardcr_flag;
|
||||||
|
unsigned char graphicsChar;
|
||||||
|
|
||||||
|
/* Set up the flags */
|
||||||
|
trim_flag = control & 1;
|
||||||
|
alldiscard_flag = control & 2;
|
||||||
|
discardctrl_flag = control & 4;
|
||||||
|
leaddiscard_flag = control & 8;
|
||||||
|
reduce_flag = control & 16;
|
||||||
|
case_flag = control & 32;
|
||||||
|
bracket_flag = control & 64;
|
||||||
|
traildiscard_flag = control & 128;
|
||||||
|
traildiscardLF_flag = control & 16384;
|
||||||
|
quote_flag = control & 256;
|
||||||
|
|
||||||
|
/* Non-BASIC extensions */
|
||||||
|
lowercase_flag = control & 512;
|
||||||
|
tab_flag = control & 1024;
|
||||||
|
untab_flag = control & 2048;
|
||||||
|
screen_flag = control & 4096; /* Convert VT220 screen prints to |,-,+
|
||||||
|
format */
|
||||||
|
discardcr_flag = control & 8192; /* Discard CR's */
|
||||||
|
|
||||||
|
/* Copy string */
|
||||||
|
i = (long)strlen(sin) + 1;
|
||||||
|
if (untab_flag) i = i * 7; /* Allow for max possible length */
|
||||||
|
sout=tempAlloc(i);
|
||||||
|
strcpy(sout,sin);
|
||||||
|
|
||||||
|
/* Discard leading space/tab */
|
||||||
|
i=0;
|
||||||
|
if (leaddiscard_flag)
|
||||||
|
while ((sout[i] != 0) && isblank_(sout[i]))
|
||||||
|
sout[i++] = 0;
|
||||||
|
|
||||||
|
/* Main processing loop */
|
||||||
|
while (sout[i] != 0) {
|
||||||
|
|
||||||
|
/* Alter characters inside quotes ? */
|
||||||
|
if (quote_flag && ((sout[i] == '"') || (sout[i] == '\'')))
|
||||||
|
processing_inside_quote = ~ processing_inside_quote;
|
||||||
|
if (processing_inside_quote) {
|
||||||
|
/* Skip the rest of the code and continue to process next character */
|
||||||
|
i++; continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Discard all space/tab */
|
||||||
|
if ((alldiscard_flag) && isblank_(sout[i]))
|
||||||
|
sout[i] = 0;
|
||||||
|
|
||||||
|
/* Trim parity (eighth?) bit */
|
||||||
|
if (trim_flag)
|
||||||
|
sout[i] = sout[i] & 0x7F;
|
||||||
|
|
||||||
|
/* Discard CR,LF,FF,ESC,BS */
|
||||||
|
if ((discardctrl_flag) && (
|
||||||
|
(sout[i] == '\015') || /* CR */
|
||||||
|
(sout[i] == '\012') || /* LF */
|
||||||
|
(sout[i] == '\014') || /* FF */
|
||||||
|
(sout[i] == '\033') || /* ESC */
|
||||||
|
/*(sout[i] == '\032') ||*/ /* ^Z */ /* DIFFERENCE won't work w/ this */
|
||||||
|
(sout[i] == '\010'))) /* BS */
|
||||||
|
sout[i] = 0;
|
||||||
|
|
||||||
|
/* Discard CR */
|
||||||
|
if ((discardcr_flag) && (
|
||||||
|
(sout[i] == '\015'))) /* CR */
|
||||||
|
sout[i] = 0;
|
||||||
|
|
||||||
|
/* Convert lowercase to uppercase */
|
||||||
|
/*
|
||||||
|
if ((case_flag) && (islower(sout[i])))
|
||||||
|
sout[i] = toupper(sout[i]);
|
||||||
|
*/
|
||||||
|
/* 13-Jun-2009 nm The upper/lower case C functions have odd behavior
|
||||||
|
with characters > 127, at least in lcc. So this was rewritten to
|
||||||
|
not use them. */
|
||||||
|
if ((case_flag) && (sout[i] >= 'a' && sout[i] <= 'z'))
|
||||||
|
sout[i] = (char)(sout[i] - ('a' - 'A'));
|
||||||
|
|
||||||
|
/* Convert [] to () */
|
||||||
|
if ((bracket_flag) && (sout[i] == '['))
|
||||||
|
sout[i] = '(';
|
||||||
|
if ((bracket_flag) && (sout[i] == ']'))
|
||||||
|
sout[i] = ')';
|
||||||
|
|
||||||
|
/* Convert uppercase to lowercase */
|
||||||
|
/*
|
||||||
|
if ((lowercase_flag) && (isupper(sout[i])))
|
||||||
|
sout[i] = tolower(sout[i]);
|
||||||
|
*/
|
||||||
|
/* 13-Jun-2009 nm The upper/lower case C functions have odd behavior
|
||||||
|
with characters > 127, at least in lcc. So this was rewritten to
|
||||||
|
not use them. */
|
||||||
|
if ((lowercase_flag) && (sout[i] >= 'A' && sout[i] <= 'Z'))
|
||||||
|
sout[i] = (char)(sout[i] + ('a' - 'A'));
|
||||||
|
|
||||||
|
/* Convert VT220 screen print frame graphics to +,|,- */
|
||||||
|
if (screen_flag) {
|
||||||
|
graphicsChar = (unsigned char)sout[i]; /* Need unsigned char for >127 */
|
||||||
|
/* vt220 */
|
||||||
|
if (graphicsChar >= 234 && graphicsChar <= 237) sout[i] = '+';
|
||||||
|
if (graphicsChar == 241) sout[i] = '-';
|
||||||
|
if (graphicsChar == 248) sout[i] = '|';
|
||||||
|
if (graphicsChar == 166) sout[i] = '|';
|
||||||
|
/* vt100 */
|
||||||
|
if (graphicsChar == 218 /*up left*/ || graphicsChar == 217 /*lo r*/
|
||||||
|
|| graphicsChar == 191 /*up r*/ || graphicsChar == 192 /*lo l*/)
|
||||||
|
sout[i] = '+';
|
||||||
|
if (graphicsChar == 196) sout[i] = '-';
|
||||||
|
if (graphicsChar == 179) sout[i] = '|';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process next character */
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
/* sout[i]=0 is the last character at this point */
|
||||||
|
|
||||||
|
/* Clean up the deleted characters */
|
||||||
|
for (j = 0, k = 0; j <= i; j++)
|
||||||
|
if (sout[j]!=0) sout[k++]=sout[j];
|
||||||
|
sout[k] = 0;
|
||||||
|
/* sout[k] = 0 is the last character at this point */
|
||||||
|
|
||||||
|
/* Discard trailing space/tab */
|
||||||
|
if (traildiscard_flag) {
|
||||||
|
--k;
|
||||||
|
while ((k >= 0) && isblank_(sout[k])) --k;
|
||||||
|
sout[++k] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8-May-2015 nm */
|
||||||
|
/* Discard trailing space/tab and LF */
|
||||||
|
if (traildiscardLF_flag) {
|
||||||
|
--k;
|
||||||
|
while ((k >= 0) && isblankorlf_(sout[k])) --k;
|
||||||
|
sout[++k] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce multiple space/tab to a single space */
|
||||||
|
if (reduce_flag) {
|
||||||
|
i = j = last_char_is_blank = 0;
|
||||||
|
while (i <= k - 1) {
|
||||||
|
if (!isblank_(sout[i])) {
|
||||||
|
sout[j++] = sout[i++];
|
||||||
|
last_char_is_blank = 0;
|
||||||
|
} else {
|
||||||
|
if (!last_char_is_blank)
|
||||||
|
sout[j++]=' '; /* Insert a space at the first occurrence of a blank */
|
||||||
|
last_char_is_blank = 1; /* Register that a blank is found */
|
||||||
|
i++; /* Process next character */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sout[j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Untab the line */
|
||||||
|
if (untab_flag || tab_flag) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
DEF FNUNTAB$(L$) ! UNTAB LINE L$
|
||||||
|
I9%=1%
|
||||||
|
I9%=INSTR(I9%,L$,CHR$(9%))
|
||||||
|
WHILE I9%
|
||||||
|
L$=LEFT(L$,I9%-1%)+SPACE$(8%-((I9%-1%) AND 7%))+RIGHT(L$,I9%+1%)
|
||||||
|
I9%=INSTR(I9%,L$,CHR$(9%))
|
||||||
|
NEXT
|
||||||
|
FNUNTAB$=L$
|
||||||
|
FNEND
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***** old code (doesn't handle multiple lines)
|
||||||
|
k = (long)strlen(sout);
|
||||||
|
for (i = 1; i <= k; i++) {
|
||||||
|
if (sout[i - 1] != '\t') continue;
|
||||||
|
for (j = k; j >= i; j--) {
|
||||||
|
sout[j + 8 - ((i - 1) & 7) - 1] = sout[j];
|
||||||
|
}
|
||||||
|
for (j = i; j < i + 8 - ((i - 1) & 7); j++) {
|
||||||
|
sout[j - 1] = ' ';
|
||||||
|
}
|
||||||
|
k = k + 8 - ((i - 1) & 7);
|
||||||
|
}
|
||||||
|
*****/
|
||||||
|
|
||||||
|
/* Untab string containing multiple lines */ /* 9-Jul-2011 nm */
|
||||||
|
/* (Currently this is needed by outputStatement() in mmpars.c) */
|
||||||
|
k = (long)strlen(sout);
|
||||||
|
m = 0; /* Position on line relative to last '\n' */
|
||||||
|
for (i = 1; i <= k; i++) {
|
||||||
|
if (sout[i - 1] == '\n') {
|
||||||
|
m = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m++; /* Should equal i for one-line string */
|
||||||
|
if (sout[i - 1] != '\t') continue;
|
||||||
|
for (j = k; j >= i; j--) {
|
||||||
|
sout[j + 8 - ((m - 1) & 7) - 1] = sout[j];
|
||||||
|
}
|
||||||
|
for (j = i; j < i + 8 - ((m - 1) & 7); j++) {
|
||||||
|
sout[j - 1] = ' ';
|
||||||
|
}
|
||||||
|
k = k + 8 - ((m - 1) & 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tab the line */
|
||||||
|
/* (Note that this does not [yet?] handle string with multiple lines) */
|
||||||
|
if (tab_flag) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
DEF FNTAB$(L$) ! TAB LINE L$
|
||||||
|
I9%=0%
|
||||||
|
FOR I9%=8% STEP 8% WHILE I9%<LEN(L$)
|
||||||
|
J9%=I9%
|
||||||
|
J9%=J9%-1% UNTIL ASCII(MID(L$,J9%,1%))<>32% OR J9%=I9%-8%
|
||||||
|
IF J9%<=I9%-2% THEN
|
||||||
|
L$=LEFT(L$,J9%)+CHR$(9%)+RIGHT(L$,I9%+1%)
|
||||||
|
I9%=J9%+1%
|
||||||
|
END IF
|
||||||
|
NEXT I9%
|
||||||
|
FNTAB$=L$
|
||||||
|
FNEND
|
||||||
|
*/
|
||||||
|
|
||||||
|
k = (long)strlen(sout);
|
||||||
|
for (i = 8; i < k; i = i + 8) {
|
||||||
|
j = i;
|
||||||
|
|
||||||
|
/* 25-May-2016 nm */
|
||||||
|
/* gcc m*.c -o metamath.exe -O2 -Wall was giving:
|
||||||
|
mmvstr.c:285:9: warning: assuming signed overflow does not occur
|
||||||
|
when assuming that (X - c) <= X is always true [-Wstrict-overflow]
|
||||||
|
Here we trick gcc into turning off this optimization by moving
|
||||||
|
the computation of i - 2 here, then referencing m instead of i - 2
|
||||||
|
below. Note that if "m = i - 2" is moved _after_ the "while", the
|
||||||
|
error message returns. */
|
||||||
|
m = i - 2;
|
||||||
|
|
||||||
|
while (sout[j - 1] == ' ' && j > i - 8) j--;
|
||||||
|
/*if (j <= i - 2) {*/
|
||||||
|
if (j <= m) { /* 25-May-2016 nm */
|
||||||
|
sout[j] = '\t';
|
||||||
|
j = i;
|
||||||
|
while (sout[j - 1] == ' ' && j > i - 8 + 1) {
|
||||||
|
sout[j - 1] = 0;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = k;
|
||||||
|
/* sout[i]=0 is the last character at this point */
|
||||||
|
/* Clean up the deleted characters */
|
||||||
|
for (j = 0, k = 0; j <= i; j++)
|
||||||
|
if (sout[j] != 0) sout[k++] = sout[j];
|
||||||
|
sout[k] = 0;
|
||||||
|
/* sout[k] = 0 is the last character at this point */
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sout);
|
||||||
|
} /* edit */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a string of the same character */
|
||||||
|
vstring string(long n, char c)
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
long j = 0;
|
||||||
|
if (n < 0) n = 0;
|
||||||
|
sout=tempAlloc(n + 1);
|
||||||
|
while (j < n) sout[j++] = c;
|
||||||
|
sout[j] = 0;
|
||||||
|
return (sout);
|
||||||
|
} /* string */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a string of spaces */
|
||||||
|
vstring space(long n)
|
||||||
|
{
|
||||||
|
return (string(n, ' '));
|
||||||
|
} /* space */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a character given its ASCII value */
|
||||||
|
vstring chr(long n)
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
sout = tempAlloc(2);
|
||||||
|
sout[0] = (char)(n & 0xFF);
|
||||||
|
sout[1] = 0;
|
||||||
|
return(sout);
|
||||||
|
} /* chr */
|
||||||
|
|
||||||
|
|
||||||
|
/* Search for string2 in string1 starting at start_position */
|
||||||
|
/* If there is no match, 0 is returned */
|
||||||
|
/* If string2 is "", (length of the string) + 1 is returned */
|
||||||
|
long instr(long start_position, vstring string1, vstring string2)
|
||||||
|
{
|
||||||
|
char *sp1, *sp2;
|
||||||
|
long ls1, ls2;
|
||||||
|
long found = 0;
|
||||||
|
if (start_position < 1) start_position = 1;
|
||||||
|
ls1 = (long)strlen(string1);
|
||||||
|
ls2 = (long)strlen(string2);
|
||||||
|
if (start_position > ls1) start_position = ls1 + 1;
|
||||||
|
sp1 = string1 + start_position - 1;
|
||||||
|
while ((sp2 = strchr(sp1, string2[0])) != 0) {
|
||||||
|
if (strncmp(sp2, string2, (size_t)ls2) == 0) {
|
||||||
|
found = sp2 - string1 + 1;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
sp1 = sp2 + 1;
|
||||||
|
}
|
||||||
|
return (found);
|
||||||
|
} /* instr */
|
||||||
|
|
||||||
|
|
||||||
|
/* 12-Jun-2011 nm Added rinstr */
|
||||||
|
/* Search for _last_ occurrence of string2 in string1 */
|
||||||
|
/* 1 = 1st string character; 0 = not found */
|
||||||
|
/* ??? Future - this could be made more efficient by searching directly,
|
||||||
|
backwards from end of string1 */
|
||||||
|
long rinstr(vstring string1, vstring string2)
|
||||||
|
{
|
||||||
|
long pos = 0;
|
||||||
|
long savePos = 0;
|
||||||
|
|
||||||
|
while (1) { /* Scan until substring no longer found */
|
||||||
|
pos = instr(pos + 1, string1, string2);
|
||||||
|
if (!pos) break;
|
||||||
|
savePos = pos;
|
||||||
|
}
|
||||||
|
return (savePos);
|
||||||
|
} /* rinstr */
|
||||||
|
|
||||||
|
|
||||||
|
/* Translate string in sin to sout based on table.
|
||||||
|
Table must be 256 characters long!! <- not true anymore? */
|
||||||
|
vstring xlate(vstring sin,vstring table)
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
long len_table, len_sin;
|
||||||
|
long i, j;
|
||||||
|
long table_entry;
|
||||||
|
char m;
|
||||||
|
len_sin = (long)strlen(sin);
|
||||||
|
len_table = (long)strlen(table);
|
||||||
|
sout = tempAlloc(len_sin+1);
|
||||||
|
for (i = j = 0; i < len_sin; i++)
|
||||||
|
{
|
||||||
|
table_entry = 0x000000FF & (long)sin[i];
|
||||||
|
if (table_entry < len_table)
|
||||||
|
if ((m = table[table_entry])!='\0')
|
||||||
|
sout[j++] = m;
|
||||||
|
}
|
||||||
|
sout[j]='\0';
|
||||||
|
return (sout);
|
||||||
|
} /* xlate */
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns the ascii value of a character */
|
||||||
|
long ascii_(vstring c)
|
||||||
|
{
|
||||||
|
return ((long)c[0]);
|
||||||
|
} /* ascii_ */
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns the floating-point value of a numeric string */
|
||||||
|
double val(vstring s)
|
||||||
|
{
|
||||||
|
double v = 0;
|
||||||
|
char signFound = 0;
|
||||||
|
double power = 1.0;
|
||||||
|
long i;
|
||||||
|
for (i = (long)strlen(s); i >= 0; i--) {
|
||||||
|
switch (s[i]) {
|
||||||
|
case '.':
|
||||||
|
v = v / power;
|
||||||
|
power = 1.0;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
signFound = 1;
|
||||||
|
break;
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
v = v + ((double)(s[i] - '0')) * power;
|
||||||
|
power = 10.0 * power;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (signFound) v = - v;
|
||||||
|
return v;
|
||||||
|
/*
|
||||||
|
return (atof(s));
|
||||||
|
*/
|
||||||
|
} /* val */
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns current date as an ASCII string */
|
||||||
|
vstring date()
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
struct tm *time_structure;
|
||||||
|
time_t time_val;
|
||||||
|
char *month[12];
|
||||||
|
|
||||||
|
/* (Aggregrate initialization is not portable) */
|
||||||
|
/* (It must be done explicitly for portability) */
|
||||||
|
month[0] = "Jan";
|
||||||
|
month[1] = "Feb";
|
||||||
|
month[2] = "Mar";
|
||||||
|
month[3] = "Apr";
|
||||||
|
month[4] = "May";
|
||||||
|
month[5] = "Jun";
|
||||||
|
month[6] = "Jul";
|
||||||
|
month[7] = "Aug";
|
||||||
|
month[8] = "Sep";
|
||||||
|
month[9] = "Oct";
|
||||||
|
month[10] = "Nov";
|
||||||
|
month[11] = "Dec";
|
||||||
|
|
||||||
|
time(&time_val); /* Retrieve time */
|
||||||
|
time_structure = localtime(&time_val); /* Translate to time structure */
|
||||||
|
sout = tempAlloc(15); /* 8-Mar-2019 nm Changed from 12 to 15 to prevent
|
||||||
|
gcc 8.3 warning (patch provided by David Starner) */
|
||||||
|
/* "%02d" means leading zeros with min. field width of 2 */
|
||||||
|
/* sprintf(sout,"%d-%s-%02d", */
|
||||||
|
sprintf(sout,"%d-%s-%04d", /* 10-Apr-06 nm 4-digit year */
|
||||||
|
time_structure->tm_mday,
|
||||||
|
month[time_structure->tm_mon],
|
||||||
|
/* time_structure->tm_year); */ /* old */
|
||||||
|
/* (int)((time_structure->tm_year) % 100)); */ /* Y2K */
|
||||||
|
(int)((time_structure->tm_year) + 1900)); /* 10-Apr-06 nm 4-digit yr */
|
||||||
|
return(sout);
|
||||||
|
} /* date */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return current time as an ASCII string */
|
||||||
|
vstring time_()
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
struct tm *time_structure;
|
||||||
|
time_t time_val;
|
||||||
|
int i;
|
||||||
|
char *format;
|
||||||
|
char *format1 = "%d:%d %s";
|
||||||
|
char *format2 = "%d:0%d %s";
|
||||||
|
char *am_pm[2];
|
||||||
|
/* (Aggregrate initialization is not portable) */
|
||||||
|
/* (It must be done explicitly for portability) */
|
||||||
|
am_pm[0] = "AM";
|
||||||
|
am_pm[1] = "PM";
|
||||||
|
|
||||||
|
time(&time_val); /* Retrieve time */
|
||||||
|
time_structure = localtime(&time_val); /* Translate to time structure */
|
||||||
|
if (time_structure->tm_hour >= 12)
|
||||||
|
i = 1;
|
||||||
|
else
|
||||||
|
i = 0;
|
||||||
|
if (time_structure->tm_hour > 12)
|
||||||
|
time_structure->tm_hour -= 12;
|
||||||
|
if (time_structure->tm_hour == 0)
|
||||||
|
time_structure->tm_hour = 12;
|
||||||
|
sout = tempAlloc(12);
|
||||||
|
if (time_structure->tm_min >= 10)
|
||||||
|
format = format1;
|
||||||
|
else
|
||||||
|
format = format2;
|
||||||
|
sprintf(sout,format,
|
||||||
|
time_structure->tm_hour,
|
||||||
|
time_structure->tm_min,
|
||||||
|
am_pm[i]);
|
||||||
|
return(sout);
|
||||||
|
} /* time */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a number as an ASCII string */
|
||||||
|
vstring str(double f)
|
||||||
|
{
|
||||||
|
/* This function converts a floating point number to a string in the */
|
||||||
|
/* same way that %f in printf does, except that trailing zeroes after */
|
||||||
|
/* the one after the decimal point are stripped; e.g., it returns 7 */
|
||||||
|
/* instead of 7.000000000000000. */
|
||||||
|
vstring s;
|
||||||
|
long i;
|
||||||
|
s = tempAlloc(50);
|
||||||
|
sprintf(s,"%f", f);
|
||||||
|
if (strchr(s, '.') != 0) { /* The string has a period in it */
|
||||||
|
for (i = (long)strlen(s) - 1; i > 0; i--) { /* Scan string backwards */
|
||||||
|
if (s[i] != '0') break; /* 1st non-zero digit */
|
||||||
|
s[i] = 0; /* Delete the trailing 0 */
|
||||||
|
}
|
||||||
|
if (s[i] == '.') s[i] = 0; /* Delete trailing period */
|
||||||
|
/*E*/INCDB1(-(49 - (long)strlen(s)));
|
||||||
|
}
|
||||||
|
return (s);
|
||||||
|
} /* str */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a number as an ASCII string */
|
||||||
|
/* (This may have differed slightly from str() in BASIC but I forgot how.
|
||||||
|
It should be considered deprecated.) */
|
||||||
|
vstring num1(double f)
|
||||||
|
{
|
||||||
|
return (str(f));
|
||||||
|
} /* num1 */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a number as an ASCII string surrounded by spaces */
|
||||||
|
/* (This should be considered deprecated.) */
|
||||||
|
vstring num(double f)
|
||||||
|
{
|
||||||
|
return (cat(" ",str(f)," ",NULL));
|
||||||
|
} /* num */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*** NEW FUNCTIONS ADDED 11/25/98 ***/
|
||||||
|
|
||||||
|
/* Emulate PROGRESS "entry" and related string functions */
|
||||||
|
/* (PROGRESS is a 4-GL database language) */
|
||||||
|
|
||||||
|
/* A "list" is a string of comma-separated elements. Example:
|
||||||
|
"a,b,c" has 3 elements. "a,b,c," has 4 elements; the last element is
|
||||||
|
an empty string. ",," has 3 elements; each is an empty string.
|
||||||
|
In "a,b,c", the entry numbers of the elements are 1, 2 and 3 (i.e.
|
||||||
|
the entry numbers start a 1, not 0). */
|
||||||
|
|
||||||
|
/* Returns a character string entry from a comma-separated
|
||||||
|
list based on an integer position. */
|
||||||
|
/* If element is less than 1 or greater than number of elements
|
||||||
|
in the list, a null string is returned. */
|
||||||
|
vstring entry(long element, vstring list)
|
||||||
|
{
|
||||||
|
vstring sout;
|
||||||
|
long commaCount, lastComma, i, length;
|
||||||
|
if (element < 1) return ("");
|
||||||
|
lastComma = -1;
|
||||||
|
commaCount = 0;
|
||||||
|
i = 0;
|
||||||
|
while (list[i] != 0) {
|
||||||
|
if (list[i] == ',') {
|
||||||
|
commaCount++;
|
||||||
|
if (commaCount == element) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastComma = i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (list[i] == 0) commaCount++;
|
||||||
|
if (element > commaCount) return ("");
|
||||||
|
length = i - lastComma - 1;
|
||||||
|
if (length < 1) return ("");
|
||||||
|
sout = tempAlloc(length + 1);
|
||||||
|
strncpy(sout, list + lastComma + 1, (size_t)length);
|
||||||
|
sout[length] = 0;
|
||||||
|
return (sout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emulate PROGRESS lookup function */
|
||||||
|
/* Returns an integer giving the first position of an expression
|
||||||
|
in a comma-separated list. Returns a 0 if the expression
|
||||||
|
is not in the list. */
|
||||||
|
long lookup(vstring expression, vstring list)
|
||||||
|
{
|
||||||
|
long i, exprNum, exprPos;
|
||||||
|
char match;
|
||||||
|
|
||||||
|
match = 1;
|
||||||
|
i = 0;
|
||||||
|
exprNum = 0;
|
||||||
|
exprPos = 0;
|
||||||
|
while (list[i] != 0) {
|
||||||
|
if (list[i] == ',') {
|
||||||
|
exprNum++;
|
||||||
|
if (match) {
|
||||||
|
if (expression[exprPos] == 0) return exprNum;
|
||||||
|
}
|
||||||
|
exprPos = 0;
|
||||||
|
match = 1;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (match) {
|
||||||
|
if (expression[exprPos] != list[i]) match = 0;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
exprPos++;
|
||||||
|
}
|
||||||
|
exprNum++;
|
||||||
|
if (match) {
|
||||||
|
if (expression[exprPos] == 0) return exprNum;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Emulate PROGRESS num-entries function */
|
||||||
|
/* Returns the number of items in a comma-separated list. If the
|
||||||
|
list is the empty string, return 0. */
|
||||||
|
long numEntries(vstring list)
|
||||||
|
{
|
||||||
|
long i, commaCount;
|
||||||
|
if (list[0] == 0) {
|
||||||
|
commaCount = -1; /* 26-Apr-2006 nm Return 0 if list empty */
|
||||||
|
} else {
|
||||||
|
commaCount = 0;
|
||||||
|
i = 0;
|
||||||
|
while (list[i] != 0) {
|
||||||
|
if (list[i] == ',') commaCount++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (commaCount + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the character position of the start of the
|
||||||
|
element in a list - useful for manipulating
|
||||||
|
the list string directly. 1 means the first string
|
||||||
|
character. */
|
||||||
|
/* If element is less than 1 or greater than number of elements
|
||||||
|
in the list, a 0 is returned. If entry is null, a 0 is
|
||||||
|
returned. */
|
||||||
|
long entryPosition(long element, vstring list)
|
||||||
|
{
|
||||||
|
long commaCount, lastComma, i;
|
||||||
|
if (element < 1) return 0;
|
||||||
|
lastComma = -1;
|
||||||
|
commaCount = 0;
|
||||||
|
i = 0;
|
||||||
|
while (list[i] != 0) {
|
||||||
|
if (list[i] == ',') {
|
||||||
|
commaCount++;
|
||||||
|
if (commaCount == element) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastComma = i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (list[i] == 0) {
|
||||||
|
if (i == 0) return 0;
|
||||||
|
if (list[i - 1] == ',') return 0;
|
||||||
|
commaCount++;
|
||||||
|
}
|
||||||
|
if (element > commaCount) return (0);
|
||||||
|
if (list[lastComma + 1] == ',') return 0;
|
||||||
|
return (lastComma + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* For debugging */
|
||||||
|
/*
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
vstringdef(s);
|
||||||
|
vstringdef(t);
|
||||||
|
|
||||||
|
printf("Hello\n");
|
||||||
|
let(&t,edit(" x y z ",2));
|
||||||
|
let(&s,cat(right("abc",2),left("def",len(right("xxx",2))),"ghi",t,NULL));
|
||||||
|
printf("%s\n",s);
|
||||||
|
printf("num %s\n",num(5));
|
||||||
|
printf("str %s\n",str(5.02));
|
||||||
|
printf("num1 %s\n",num1(5.02));
|
||||||
|
printf("time_ %s\n",time_());
|
||||||
|
printf("date %s\n",date());
|
||||||
|
printf("val %f\n",val("6.77"));
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
199
mmvstr.h
Normal file
199
mmvstr.h
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2011 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
mmvstr.h - VMS-BASIC variable length string library routines header
|
||||||
|
This is an emulation of the string functions available in VMS BASIC.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
Variable-length string handler
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
This collection of string-handling functions emulate most of the
|
||||||
|
string functions of VMS BASIC. The objects manipulated by these
|
||||||
|
functions are strings of a special type called 'vstring' which have no
|
||||||
|
pre-defined upper length limit but are dynamically allocated and
|
||||||
|
deallocated as needed. To use the vstring functions within a program,
|
||||||
|
all vstrings must be initially set to the null string when declared or
|
||||||
|
before first used, for example:
|
||||||
|
|
||||||
|
vstring string1 = "";
|
||||||
|
vstring stringArray[] = {"", "", ""};
|
||||||
|
|
||||||
|
vstring bigArray[100][10]; /- Must be initialized before using -/
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < 100; i++)
|
||||||
|
for (j = 0; j < 10; j++)
|
||||||
|
bigArray[i][j] = ""; /- Initialize -/
|
||||||
|
|
||||||
|
|
||||||
|
After initialization, vstrings should be assigned with the 'let(&'
|
||||||
|
function only; for example the statements
|
||||||
|
|
||||||
|
let(&string1, "abc");
|
||||||
|
let(&string1, string2);
|
||||||
|
let(&string1, left(string2, 3));
|
||||||
|
|
||||||
|
all assign the second argument to 'string1'. The 'let(&' function must
|
||||||
|
_not_ be used to initialize a vstring the first time.
|
||||||
|
|
||||||
|
Any local vstrings in a function must be deallocated before returning
|
||||||
|
from the function, otherwise there will be memory leakage and eventual
|
||||||
|
memory overflow. To deallocate, assign the vstring to "" with 'let(&':
|
||||||
|
|
||||||
|
void abc(void) {
|
||||||
|
vstring xyz = "";
|
||||||
|
...
|
||||||
|
let(&xyz, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
The 'cat' function emulates the '+' concatenation operator in BASIC.
|
||||||
|
It has a variable number of arguments, and the last argument should always
|
||||||
|
be NULL. For example,
|
||||||
|
|
||||||
|
let(&string1,cat("abc","def",NULL));
|
||||||
|
|
||||||
|
assigns "abcdef" to 'string1'. Warning: 0 will work instead of NULL on the
|
||||||
|
VAX but not on the Macintosh, so always use NULL.
|
||||||
|
|
||||||
|
All other functions are generally used exactly like their BASIC
|
||||||
|
equivalents. For example, the BASIC statement
|
||||||
|
|
||||||
|
let string1$=left$("def",len(right$("xxx",2)))+"ghi"+string2$
|
||||||
|
|
||||||
|
is emulated in c as
|
||||||
|
|
||||||
|
let(&string1,cat(left("def",len(right("xxx",2))),"ghi",string2,NULL));
|
||||||
|
|
||||||
|
Note that ANSII c does not allow "$" as part of an identifier
|
||||||
|
name, so the names in c have had the "$" suffix removed.
|
||||||
|
|
||||||
|
The string arguments of the vstring functions may be either standard c
|
||||||
|
strings or vstrings (except that the first argument of the 'let(&' function
|
||||||
|
must be a vstring). The standard c string functions may use vstrings or
|
||||||
|
vstring functions as their string arguments, as long as the vstring variable
|
||||||
|
itself (which is a char * pointer) is not modified and no attempt is made to
|
||||||
|
increase the length of a vstring. Caution must be excercised when
|
||||||
|
assigning standard c string pointers to vstrings or the results of
|
||||||
|
vstring functions, as the memory space may be deallocated when the
|
||||||
|
'let(&' function is next executed. For example,
|
||||||
|
|
||||||
|
char *stdstr; /- A standard c string pointer -/
|
||||||
|
...
|
||||||
|
stdstr=left("abc",2);
|
||||||
|
|
||||||
|
will assign "ab" to 'stdstr', but this assignment will be lost when the
|
||||||
|
next 'let(&' function is executed. To be safe, use 'strcpy':
|
||||||
|
|
||||||
|
char stdstr1[80]; /- A fixed length standard c string -/
|
||||||
|
...
|
||||||
|
strcpy(stdstr1,left("abc",2));
|
||||||
|
|
||||||
|
Here, of course, the user must ensure that the string copied to 'stdstr1'
|
||||||
|
does not exceed 79 characters in length.
|
||||||
|
|
||||||
|
The vstring functions allocate temporary memory whenever they are called.
|
||||||
|
This temporary memory is deallocated whenever a 'let(&' assignment is
|
||||||
|
made. The user should be aware of this when using vstring functions
|
||||||
|
outside of 'let(&' assignments; for example
|
||||||
|
|
||||||
|
for (i=0; i<10000; i++)
|
||||||
|
print2("%s\n",left(string1,70));
|
||||||
|
|
||||||
|
will allocate another 70 bytes or so of memory each pass through the loop.
|
||||||
|
If necessary, dummy 'let(&' assignments can be made periodically to clear
|
||||||
|
this temporary memory:
|
||||||
|
|
||||||
|
for (i=0; i<10000; i++)
|
||||||
|
{
|
||||||
|
print2("%s\n",left(string1,70));
|
||||||
|
let(&dummy,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
It should be noted that the 'linput' function assigns its target string
|
||||||
|
with 'let(&' and thus has the same effect as 'let(&'.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMVSTR_H_
|
||||||
|
#define METAMATH_MMVSTR_H_
|
||||||
|
|
||||||
|
typedef char* vstring;
|
||||||
|
#define vstringdef(x) vstring x = ""
|
||||||
|
|
||||||
|
/* Emulation of BASIC string assignment */
|
||||||
|
/* 'let' MUST be used to assign vstrings, e.g. 'let(&abc, "Hello"); */
|
||||||
|
/* Empty string deallocates memory, e.g. 'let(&abc, ""); */
|
||||||
|
void let(vstring *target, vstring source);
|
||||||
|
|
||||||
|
/* Emulation of BASIC string concatenation - last argument MUST be NULL */
|
||||||
|
/* vstring cat(vstring string1, ..., stringN, NULL); */
|
||||||
|
/* e.g. 'let(&abc, cat("Hello", " ", left("worldx", 5), "!", NULL);' */
|
||||||
|
vstring cat(vstring string1,...);
|
||||||
|
|
||||||
|
/* Emulation of BASIC linput (line input) statement; returns NULL if EOF */
|
||||||
|
/* Note that linput assigns target string with let(&target,...) */
|
||||||
|
/*
|
||||||
|
BASIC: linput "what";a$
|
||||||
|
c: linput(NULL,"what?",&a);
|
||||||
|
|
||||||
|
BASIC: linput #1,a$ (error trap on EOF)
|
||||||
|
c: if (!linput(file1,NULL,&a)) break; (break on EOF)
|
||||||
|
|
||||||
|
*/
|
||||||
|
/* returns whether a (possibly empty) line was successfully read */
|
||||||
|
int linput(FILE *stream,const char* ask,vstring *target);
|
||||||
|
|
||||||
|
/* Emulation of BASIC string functions */
|
||||||
|
/* Indices are 1-based */
|
||||||
|
vstring seg(vstring sin, long p1, long p2);
|
||||||
|
vstring mid(vstring sin, long p, long l);
|
||||||
|
vstring left(vstring sin, long n);
|
||||||
|
vstring right(vstring sin, long n);
|
||||||
|
vstring edit(vstring sin, long control);
|
||||||
|
vstring space(long n);
|
||||||
|
vstring string(long n, char c);
|
||||||
|
vstring chr(long n);
|
||||||
|
vstring xlate(vstring sin, vstring control);
|
||||||
|
vstring date(void);
|
||||||
|
vstring time_(void);
|
||||||
|
vstring num(double x);
|
||||||
|
vstring num1(double x);
|
||||||
|
vstring str(double x);
|
||||||
|
long len(vstring s);
|
||||||
|
long instr(long start, vstring sin, vstring s);
|
||||||
|
long rinstr(vstring string1, vstring string2);
|
||||||
|
long ascii_(vstring c);
|
||||||
|
double val(vstring s);
|
||||||
|
|
||||||
|
/* Emulation of Progress 4GL string functions, added 11/25/98 */
|
||||||
|
vstring entry(long element, vstring list);
|
||||||
|
long lookup(vstring expression, vstring list);
|
||||||
|
long numEntries(vstring list);
|
||||||
|
long entryPosition(long element, vstring list);
|
||||||
|
|
||||||
|
/* Routines may/may not be written (lowest priority):
|
||||||
|
vstring place$(vstring sout);
|
||||||
|
vstring prod$(vstring sout);
|
||||||
|
vstring quo$(vstring sout);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******* Special purpose routines for better
|
||||||
|
memory allocation (use with caution) *******/
|
||||||
|
|
||||||
|
extern long g_tempAllocStackTop; /* Top of stack for tempAlloc functon */
|
||||||
|
extern long g_startTempAllocStack; /* Where to start freeing temporary allocation
|
||||||
|
when let() is called (normally 0, except for nested vstring functions) */
|
||||||
|
|
||||||
|
/* Make string have temporary allocation to be released by next let() */
|
||||||
|
/* Warning: after makeTempAlloc() is called, the vstring may NOT be
|
||||||
|
assigned again with let() */
|
||||||
|
void makeTempAlloc(vstring s); /* Make string have temporary allocation to be
|
||||||
|
released by next let() */
|
||||||
|
#endif /* METAMATH_MMVSTR_H_ */
|
612
mmword.c
Normal file
612
mmword.c
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2012 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
/* This file implements the UPDATE command of the TOOLS utility. revise() is
|
||||||
|
the main external call; see the comments preceding it. */
|
||||||
|
|
||||||
|
/* The UPDATE command of TOOLS (mmword.c) was custom-written in accordance
|
||||||
|
with the version control requirements of a company that used it. It
|
||||||
|
documents the differences between two versions of a program as C-style
|
||||||
|
comments embedded in the newer version. The best way to determine whether
|
||||||
|
it suits your similar needs is just to run it and look at its output. */
|
||||||
|
|
||||||
|
/* Very old history: this was called mmword.c because it was intended to
|
||||||
|
produce RTF output for Word, analogous to the existing LaTeX output.
|
||||||
|
Microsoft never responded to a request for the RTF specification, as they
|
||||||
|
promised in the circa 1990 manual accompanying Word. Thus it remained an
|
||||||
|
empty shell. When the need for UPDATE arose, the mmword.c shell was used in
|
||||||
|
order to avoid the nuisance of changing some compilation setups and scripts
|
||||||
|
existing at that time. */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
#include "mminou.h"
|
||||||
|
#include "mmword.h"
|
||||||
|
|
||||||
|
/* Set to 79, 80, etc. - length of line after tag is added */
|
||||||
|
#define LINE_LENGTH 80
|
||||||
|
|
||||||
|
|
||||||
|
/* 7000 ! ***** "DIFF" Option ***** from DO LIST */
|
||||||
|
/* gosub_7000(f1_name, f2_name, f3_name, &f3_fp, m); */
|
||||||
|
|
||||||
|
|
||||||
|
char strcmpe(vstring s1, vstring s2);
|
||||||
|
vstring stripAndTag(vstring line, vstring tag, flag tagBlankLines);
|
||||||
|
|
||||||
|
long r0,r1,r2,i0,i1_,i2_,d,t,i9;
|
||||||
|
FILE *f1_fp_;
|
||||||
|
FILE *f2_fp_;
|
||||||
|
FILE *f3_fp_;
|
||||||
|
char eof1, eof2;
|
||||||
|
vstring ctlz_ = "";
|
||||||
|
vstring l1_ = "";
|
||||||
|
vstring l2_ = "";
|
||||||
|
vstring tmp_ = "";
|
||||||
|
vstring tmpLine = "";
|
||||||
|
vstring addTag_ = "";
|
||||||
|
vstring delStartTag_ = "";
|
||||||
|
vstring delEndTag_ = "";
|
||||||
|
flag printedAtLeastOne;
|
||||||
|
/* Declare input and save buffers */
|
||||||
|
#define MAX_LINES 10000
|
||||||
|
#define MAX_BUF 1000
|
||||||
|
vstring line1_[MAX_LINES];
|
||||||
|
vstring line2_[MAX_LINES];
|
||||||
|
vstring reserve1_[MAX_BUF];
|
||||||
|
vstring reserve2_[MAX_BUF];
|
||||||
|
|
||||||
|
|
||||||
|
/* revise() is called by the UPDATE command of TOOLs. The idea is to
|
||||||
|
keep all past history of a file in the file itself, in the form of
|
||||||
|
comments. In mmcmds.c, see the parsing of the UPDATE command for a
|
||||||
|
partial explanation of its arguments. UPDATE was written for a
|
||||||
|
proprietary language with C-style comments (where nested comments were
|
||||||
|
allowed) and it may not be generally useful without some modification. */
|
||||||
|
void revise(FILE *f1_fp, FILE *f2_fp, FILE *f3_fp, vstring addTag, long m)
|
||||||
|
{
|
||||||
|
/******** Figure out the differences (DO LIST subroutine) ******/
|
||||||
|
vstring blanksPrefix = "";
|
||||||
|
long tmpi;
|
||||||
|
long i, j;
|
||||||
|
|
||||||
|
f1_fp_ = f1_fp;
|
||||||
|
f2_fp_ = f2_fp;
|
||||||
|
f3_fp_ = f3_fp;
|
||||||
|
let(&addTag_, addTag);
|
||||||
|
let(&delStartTag_, "/******* Start of deleted section *******");
|
||||||
|
let(&delEndTag_, "******* End of deleted section *******/");
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize vstring arrays */
|
||||||
|
for (i = 0; i < MAX_LINES; i++) {
|
||||||
|
line1_[i] = "";
|
||||||
|
line2_[i] = "";
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_BUF; i++) {
|
||||||
|
reserve1_[i] = "";
|
||||||
|
reserve2_[i] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m < 1) m = 1;
|
||||||
|
|
||||||
|
r0=r1=r2=i0=i1_=i2_=d=t=i=j=i9=0;
|
||||||
|
|
||||||
|
|
||||||
|
let(&ctlz_,chr(26)); /* End-of-file character */
|
||||||
|
|
||||||
|
let(&l1_,ctlz_);
|
||||||
|
let(&l2_,ctlz_);
|
||||||
|
eof1=eof2=0; /* End-of-file flags */
|
||||||
|
d=0;
|
||||||
|
|
||||||
|
l7100: /*
|
||||||
|
Lines 7100 through 7300 are a modified version of the compare loop
|
||||||
|
In DEC's FILCOM.BAS program.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!strcmpe(l1_,l2_)) { /* The lines are the same */
|
||||||
|
if (strcmpe(l2_,ctlz_)) {
|
||||||
|
fprintf(f3_fp_, "%s\n", l2_); /* Use edited version
|
||||||
|
of line when they are the same */
|
||||||
|
}
|
||||||
|
gosub_7320();
|
||||||
|
gosub_7330();
|
||||||
|
if (strcmpe(l1_,ctlz_) || strcmpe(l2_,ctlz_) ) {
|
||||||
|
goto l7100;
|
||||||
|
} else {
|
||||||
|
fclose(f1_fp_);
|
||||||
|
fclose(f2_fp_);
|
||||||
|
fclose(f3_fp_);
|
||||||
|
|
||||||
|
/* Deallocate string memory */
|
||||||
|
for (i = 0; i < MAX_LINES; i++) {
|
||||||
|
let(&(line1_[i]), "");
|
||||||
|
let(&(line2_[i]), "");
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_BUF; i++) {
|
||||||
|
let(&(reserve1_[i]), "");
|
||||||
|
let(&(reserve2_[i]), "");
|
||||||
|
}
|
||||||
|
let(&ctlz_, "");
|
||||||
|
let(&l1_, "");
|
||||||
|
let(&l2_, "");
|
||||||
|
let(&tmp_, "");
|
||||||
|
let(&tmpLine, "");
|
||||||
|
let(&addTag_, "");
|
||||||
|
let(&delStartTag_, "");
|
||||||
|
let(&delEndTag_, "");
|
||||||
|
let(&blanksPrefix, "");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d=d+1; /* Number of difference sections found so far
|
||||||
|
(For user information only) */
|
||||||
|
i1_=i2_=m-1;
|
||||||
|
let(&line1_[0],l1_);
|
||||||
|
let(&line2_[0],l2_);
|
||||||
|
for (i0 = 1; i0 < m; i0++) {
|
||||||
|
gosub_7320();
|
||||||
|
let(&line1_[i0],l1_);
|
||||||
|
}
|
||||||
|
for (i0 = 1; i0 < m; i0++) {
|
||||||
|
gosub_7330();
|
||||||
|
let(&line2_[i0],l2_);
|
||||||
|
}
|
||||||
|
l7130: gosub_7320();
|
||||||
|
i1_=i1_+1;
|
||||||
|
if (i1_ >= MAX_LINES) {
|
||||||
|
printf("*** FATAL *** Overflow#1\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
let(&line1_[i1_],l1_);
|
||||||
|
t=0;
|
||||||
|
i=0;
|
||||||
|
l7140: if (strcmpe(line1_[i1_+t-m+1], line2_[i+t])) {
|
||||||
|
t=0;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* If lines "match", ensure we use the EDITED version for the
|
||||||
|
final output */
|
||||||
|
let(&line1_[i1_+t-m+1], line2_[i+t]);
|
||||||
|
|
||||||
|
t=t+1;
|
||||||
|
if (t==m) {
|
||||||
|
goto l7200;
|
||||||
|
} else {
|
||||||
|
goto l7140;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i=i+1;
|
||||||
|
if (i<=i2_-m+1) {
|
||||||
|
goto l7140;
|
||||||
|
}
|
||||||
|
gosub_7330();
|
||||||
|
i2_=i2_+1;
|
||||||
|
if (i2_ >= MAX_LINES) {
|
||||||
|
printf("*** FATAL *** Overflow#2\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
let(&line2_[i2_],l2_);
|
||||||
|
t=0;
|
||||||
|
i=0;
|
||||||
|
l7170:
|
||||||
|
if (strcmpe(line1_[i+t], line2_[i2_+t-m+1])) {
|
||||||
|
t=0;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* If lines "match", ensure we use the EDITED version for the
|
||||||
|
final output */
|
||||||
|
let(&line1_[i+t], line2_[i2_+t-m+1]);
|
||||||
|
|
||||||
|
t=t+1;
|
||||||
|
if (t==m) {
|
||||||
|
goto l7220;
|
||||||
|
} else {
|
||||||
|
goto l7170;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=i+1;
|
||||||
|
if (i<=i1_-m+1) {
|
||||||
|
goto l7170;
|
||||||
|
}
|
||||||
|
goto l7130;
|
||||||
|
l7200: i=i+m-1;
|
||||||
|
if (r2) {
|
||||||
|
for (j=r2-1; j>=0; j--) {
|
||||||
|
let(&reserve2_[j+i2_-i],reserve2_[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j=1; j<=i2_-i; j++) {
|
||||||
|
let(&reserve2_[j-1],line2_[j+i]);
|
||||||
|
}
|
||||||
|
r2=r2+i2_-i;
|
||||||
|
if (r2 >= MAX_BUF) {
|
||||||
|
printf("*** FATAL *** Overflow#3\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
i2_=i;
|
||||||
|
goto l7240;
|
||||||
|
l7220: i=i+m-1;
|
||||||
|
if (r1) {
|
||||||
|
for (j=r1-1; j>=0; j--) {
|
||||||
|
let(&reserve1_[j+i1_-i],reserve1_[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j=1; j<=i1_-i; j++) {
|
||||||
|
let(&reserve1_[j-1],line1_[j+i]);
|
||||||
|
}
|
||||||
|
r1=r1+i1_-i;
|
||||||
|
if (r1 >= MAX_BUF) {
|
||||||
|
printf("*** FATAL *** Overflow#4\n");
|
||||||
|
#if __STDC__
|
||||||
|
fflush(stdout);
|
||||||
|
#endif
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
i1_=i;
|
||||||
|
goto l7240;
|
||||||
|
l7240: /* */
|
||||||
|
|
||||||
|
printedAtLeastOne = 0;
|
||||||
|
for (i=0; i<=i1_-m; i++) {
|
||||||
|
if (strcmpe(line1_[i],ctlz_)) {
|
||||||
|
if (!printedAtLeastOne) {
|
||||||
|
printedAtLeastOne = 1;
|
||||||
|
|
||||||
|
/* Put out any blank lines before delStartTag_ */
|
||||||
|
while (((vstring)(line1_[i]))[0] == '\n') {
|
||||||
|
fprintf(f3_fp_, "\n");
|
||||||
|
let(&(line1_[i]), right(line1_[i], 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the beginning blank space */
|
||||||
|
tmpi = 0;
|
||||||
|
while (((vstring)(line1_[i]))[tmpi] == ' ') tmpi++;
|
||||||
|
let(&blanksPrefix, space(tmpi));
|
||||||
|
let(&tmpLine, "");
|
||||||
|
tmpLine = stripAndTag(cat(blanksPrefix, delStartTag_, NULL),
|
||||||
|
addTag_, 0);
|
||||||
|
fprintf(f3_fp_, "%s\n", tmpLine);
|
||||||
|
}
|
||||||
|
fprintf(f3_fp_, "%s\n", line1_[i]);
|
||||||
|
/* Output original deleted lines */
|
||||||
|
/*let(&tmp_, "");*/ /* Clear vstring stack */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (printedAtLeastOne) {
|
||||||
|
let(&tmpLine, "");
|
||||||
|
tmpLine = stripAndTag(cat(blanksPrefix, delEndTag_, NULL), addTag_
|
||||||
|
,0);
|
||||||
|
fprintf(f3_fp_, "%s\n", tmpLine);
|
||||||
|
}
|
||||||
|
for (i=0; i<=i1_-m; i++) {
|
||||||
|
if (i<=i2_-m) {
|
||||||
|
if (strcmpe(line2_[i],ctlz_)) {
|
||||||
|
let(&tmpLine, "");
|
||||||
|
if (i == 0) {
|
||||||
|
tmpLine = stripAndTag(line2_[i], addTag_, 0);
|
||||||
|
} else {
|
||||||
|
/* Put tags on blank lines *inside* of new section */
|
||||||
|
tmpLine = stripAndTag(line2_[i], addTag_, 1);
|
||||||
|
}
|
||||||
|
fprintf(f3_fp_, "%s\n", tmpLine);
|
||||||
|
/* Output tagged edited lines */
|
||||||
|
/*let(&tmp_, "");*/ /* Clear vstring stack */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=i1_-m+1; i<=i2_-m; i++) {
|
||||||
|
if (strcmpe(line2_[i],ctlz_)) {
|
||||||
|
let(&tmpLine, "");
|
||||||
|
if (i == 0) {
|
||||||
|
tmpLine = stripAndTag(line2_[i], addTag_, 0);
|
||||||
|
} else {
|
||||||
|
/* Put tags on blank lines *inside* of new section */
|
||||||
|
tmpLine = stripAndTag(line2_[i], addTag_, 1);
|
||||||
|
}
|
||||||
|
fprintf(f3_fp_, "%s\n", tmpLine);
|
||||||
|
/* Print remaining edited lines */
|
||||||
|
/*let(&tmp_, "");*/ /* Clear vstring stack */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=0; i<=m-1; i++) {
|
||||||
|
let(&l1_,line1_[i1_-m+1+i]);
|
||||||
|
if (strcmpe(l1_,ctlz_)) {
|
||||||
|
fprintf(f3_fp_,"%s\n",l1_); /* Print remaining matching lines */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let(&l1_,ctlz_);
|
||||||
|
let(&l2_,ctlz_);
|
||||||
|
goto l7100;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void gosub_7320()
|
||||||
|
{
|
||||||
|
/* Subroutine: get next L1_ from original file */
|
||||||
|
vstring tmpLin = "";
|
||||||
|
if (r1) { /* Get next line from save array */
|
||||||
|
let(&l1_,reserve1_[0]);
|
||||||
|
r1=r1-1;
|
||||||
|
for (i9=0; i9<=r1-1; i9++) {
|
||||||
|
let(&reserve1_[i9],reserve1_[i9+1]);
|
||||||
|
}
|
||||||
|
} else { /* Get next line from input file */
|
||||||
|
if (eof1) {
|
||||||
|
let(&l1_,ctlz_);
|
||||||
|
} else {
|
||||||
|
next_l1:
|
||||||
|
if (!linput(f1_fp_,NULL,&l1_)) { /*linput returns 0 if EOF */
|
||||||
|
eof1 = 1;
|
||||||
|
/* Note that we will discard any blank lines before EOF; this
|
||||||
|
should be OK though */
|
||||||
|
let(&l1_,ctlz_);
|
||||||
|
let(&tmpLin, ""); /* Deallocate */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let(&l1_, edit(l1_, 4 + 128 + 2048)); /* Trim garb, trail space; untab */
|
||||||
|
if (!l1_[0]) { /* Ignore blank lines for comparison */
|
||||||
|
let(&tmpLin, cat(tmpLin, "\n", NULL)); /* Blank line */
|
||||||
|
goto next_l1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let(&l1_, cat(tmpLin, l1_, NULL)); /* Add any blank lines */
|
||||||
|
let(&tmpLin, ""); /* Deallocate */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gosub_7330() {
|
||||||
|
/* Subroutine: get next L2_ from edited file */
|
||||||
|
vstring tmpLin = "";
|
||||||
|
vstring tmpStrPtr; /* pointer only */
|
||||||
|
flag stripDeletedSectionMode;
|
||||||
|
if (r2) { /* Get next line from save array */
|
||||||
|
let(&l2_,reserve2_[0]);
|
||||||
|
r2=r2-1;
|
||||||
|
for (i9 = 0; i9 < r2; i9++) {
|
||||||
|
let(&reserve2_[i9],reserve2_[i9+1]);
|
||||||
|
}
|
||||||
|
} else { /* Get next line from input file */
|
||||||
|
if (eof2) {
|
||||||
|
let(&l2_,ctlz_);
|
||||||
|
} else {
|
||||||
|
stripDeletedSectionMode = 0;
|
||||||
|
next_l2:
|
||||||
|
if (!linput(f2_fp_,NULL,&l2_)) { /* linput returns 0 if EOF */
|
||||||
|
eof2 = 1;
|
||||||
|
/* Note that we will discard any blank lines before EOF; this
|
||||||
|
should be OK though */
|
||||||
|
let(&l2_, ctlz_);
|
||||||
|
let(&tmpLin, ""); /* Deallocate */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let(&l2_, edit(l2_, 4 + 128 + 2048)); /* Trim garb, trail space; untab */
|
||||||
|
if (!strcmp(edit(delStartTag_, 2), left(edit(l2_, 2 + 4),
|
||||||
|
(long)strlen(edit(delStartTag_, 2))))) {
|
||||||
|
if (getRevision(l2_) == getRevision(addTag_)) {
|
||||||
|
/* We should strip out deleted section from previous run */
|
||||||
|
/* (The diff algorithm will put them back from orig. file) */
|
||||||
|
stripDeletedSectionMode = 1;
|
||||||
|
goto next_l2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stripDeletedSectionMode) {
|
||||||
|
if (!strcmp(edit(delEndTag_, 2), left(edit(l2_, 2 + 4),
|
||||||
|
(long)strlen(edit(delEndTag_, 2)))) &&
|
||||||
|
getRevision(l2_) == getRevision(addTag_) ) {
|
||||||
|
stripDeletedSectionMode = 0;
|
||||||
|
}
|
||||||
|
goto next_l2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip off tags that match *this* revision (so previous out-of-sync
|
||||||
|
runs will be corrected) */
|
||||||
|
if (getRevision(l2_) == getRevision(addTag_)) {
|
||||||
|
tmpStrPtr = l2_;
|
||||||
|
l2_ = stripAndTag(l2_, "", 0);
|
||||||
|
let(&tmpStrPtr, ""); /* deallocate old l2_ */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l2_[0]) { /* Ignore blank lines for comparison */
|
||||||
|
let(&tmpLin, cat(tmpLin, "\n", NULL)); /* Blank line */
|
||||||
|
goto next_l2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let(&l2_, cat(tmpLin, l2_, NULL)); /* Add any blank lines */
|
||||||
|
let(&tmpLin, ""); /* Deallocate */
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return 0 if difference lines are the same, non-zero otherwise */
|
||||||
|
char strcmpe(vstring s1, vstring s2)
|
||||||
|
{
|
||||||
|
flag cmpflag;
|
||||||
|
|
||||||
|
/* Option flags - make global if we want to use them */
|
||||||
|
flag ignoreSpaces = 1;
|
||||||
|
flag ignoreSameLineComments = 1;
|
||||||
|
|
||||||
|
vstring tmps1 = "";
|
||||||
|
vstring tmps2 = "";
|
||||||
|
long i;
|
||||||
|
long i2;
|
||||||
|
long i3;
|
||||||
|
let(&tmps1, s1);
|
||||||
|
let(&tmps2, s2);
|
||||||
|
|
||||||
|
if (ignoreSpaces) {
|
||||||
|
let(&tmps1, edit(tmps1, 2 + 4));
|
||||||
|
let(&tmps2, edit(tmps2, 2 + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoreSameLineComments) {
|
||||||
|
while (1) {
|
||||||
|
i = instr(1, tmps1, "/*");
|
||||||
|
if (i == 0) break;
|
||||||
|
i2 = instr(i + 2, tmps1, "*/");
|
||||||
|
if (i2 == 0) break;
|
||||||
|
i3 = instr(i + 2, tmps1, "/*");
|
||||||
|
if (i3 != 0 && i3 < i2) break; /*i = i3;*/ /* Nested comment */
|
||||||
|
if (i2 - i > 7) break; /* only ignore short comments (tags) */
|
||||||
|
let(&tmps1, cat(left(tmps1, i - 1), right(tmps1, i2 + 2), NULL));
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
i = instr(1, tmps2, "/*");
|
||||||
|
if (i == 0) break;
|
||||||
|
i2 = instr(i + 2, tmps2, "*/");
|
||||||
|
if (i2 == 0) break;
|
||||||
|
i3 = instr(i + 2, tmps2, "/*");
|
||||||
|
if (i3 != 0 && i3 < i2) break; /*i = i3;*/ /* Nested comment */
|
||||||
|
if (i2 - i > 7) break; /* only ignore short comments (tags) */
|
||||||
|
let(&tmps2, cat(left(tmps2, i - 1), right(tmps2, i2 + 2), NULL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmpflag = !!strcmp(tmps1, tmps2);
|
||||||
|
let(&tmps1, ""); /* Deallocate string */
|
||||||
|
let(&tmps2, ""); /* Deallocate string */
|
||||||
|
return (cmpflag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Strip any old tag from line and put new tag on it */
|
||||||
|
/* (Caller must deallocate returned string) */
|
||||||
|
vstring stripAndTag(vstring line, vstring tag, flag tagBlankLines)
|
||||||
|
{
|
||||||
|
long i, j, k, n;
|
||||||
|
vstring line1 = "", comment = "";
|
||||||
|
long lineLength = LINE_LENGTH;
|
||||||
|
flag validTag;
|
||||||
|
i = 0;
|
||||||
|
let(&line1, edit(line, 128 + 2048)); /* Trim trailing spaces and untab */
|
||||||
|
/* Get last comment on line */
|
||||||
|
while (1) {
|
||||||
|
j = instr(i + 1, line1, "/*");
|
||||||
|
if (j == 0) break;
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
j = instr(i, line1, "*/");
|
||||||
|
if (i && j == (signed)(strlen(line1)) - 1) {
|
||||||
|
let(&comment, seg(line1, i + 2, j - 1));
|
||||||
|
validTag = 1;
|
||||||
|
for (k = 0; k < (signed)(strlen(comment)); k++) {
|
||||||
|
/* Check for valid characters that can appear in a tag */
|
||||||
|
if (instr(1, " 1234567890#", mid(comment, k + 1, 1))) continue;
|
||||||
|
validTag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (validTag) let(&line1, edit(left(line1, i - 1), 128));
|
||||||
|
let(&comment, ""); /* deallocate */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count blank lines concatenated to the beginning of this line */
|
||||||
|
n = 0;
|
||||||
|
while (line1[n] == '\n') n++;
|
||||||
|
|
||||||
|
/* Add the tag */
|
||||||
|
if (tag[0]) { /* Non-blank tag */
|
||||||
|
if ((long)strlen(line1) - n < lineLength - 1 - (long)strlen(tag))
|
||||||
|
let(&line1, cat(line1,
|
||||||
|
space(lineLength - 1 - (long)strlen(tag) - (long)strlen(line1) + n),
|
||||||
|
NULL));
|
||||||
|
let(&line1, cat(line1, " ", tag, NULL));
|
||||||
|
if ((signed)(strlen(line1)) - n > lineLength) {
|
||||||
|
print2(
|
||||||
|
"Warning: The following line has > %ld characters after tag is added:\n",
|
||||||
|
lineLength);
|
||||||
|
print2("%s\n", line1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add tags to blank lines if tagBlankLines is set */
|
||||||
|
/* (Used for blank lines inside of new edited file sections) */
|
||||||
|
if (tagBlankLines && n > 0) {
|
||||||
|
let(&line1, right(line1, n + 1));
|
||||||
|
for (i = 1; i <= n; i++) {
|
||||||
|
let(&line1, cat(space(lineLength - (long)strlen(tag)), tag, "\n",
|
||||||
|
line1, NULL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return line1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the largest revision number tag in a file */
|
||||||
|
/* Tags are assumed to be of format nn or #nn in comment at end of line */
|
||||||
|
/* Used to determine default argument for tag question */
|
||||||
|
long highestRevision(vstring fileName)
|
||||||
|
{
|
||||||
|
vstring str1 = "";
|
||||||
|
long revision;
|
||||||
|
long largest = 0;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(fileName, "r");
|
||||||
|
if (!fp) return 0;
|
||||||
|
while (linput(fp, NULL, &str1)) {
|
||||||
|
revision = getRevision(str1);
|
||||||
|
if (revision > largest) largest = revision;
|
||||||
|
}
|
||||||
|
let(&str1, "");
|
||||||
|
fclose(fp);
|
||||||
|
return largest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get numeric revision from the tag on a line (returns 0 if none) */
|
||||||
|
/* Tags are assumed to be of format nn or #nn in comment at end of line */
|
||||||
|
long getRevision(vstring line)
|
||||||
|
{
|
||||||
|
vstring str1 = "";
|
||||||
|
vstring str2 = "";
|
||||||
|
vstring tag = "";
|
||||||
|
long revision;
|
||||||
|
|
||||||
|
if (instr(1, line, "/*") == 0) return 0; /* Speedup - no comment in line */
|
||||||
|
let(&str1, edit(line, 2)); /* This line has the tag not stripped */
|
||||||
|
let(&str2, "");
|
||||||
|
str2 = stripAndTag(str1, "", 0); /* Strip old tag & add dummy new one */
|
||||||
|
let(&str2, edit(str2, 2)); /* This line has the tag stripped */
|
||||||
|
if (!strcmp(str1, str2)) {
|
||||||
|
revision = 0; /* No tag */
|
||||||
|
} else {
|
||||||
|
let(&tag, edit(seg(str1, (long)strlen(str2) + 3,
|
||||||
|
(long)strlen(str1) - 2), 2));
|
||||||
|
if (tag[0] == '#') let(&tag, right(tag, 2)); /* Remove any # */
|
||||||
|
revision = (long)(val(tag));
|
||||||
|
}
|
||||||
|
let(&tag, "");
|
||||||
|
let(&str1, "");
|
||||||
|
let(&str2, "");
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
33
mmword.h
Normal file
33
mmword.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2012 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMWORD_H_
|
||||||
|
#define METAMATH_MMWORD_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
|
||||||
|
/* Tag file changes with revision number tags */
|
||||||
|
void revise(FILE *f1_fp, FILE *f2_fp, FILE *f3_fp, vstring addTag, long m);
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the largest revision number tag in a file */
|
||||||
|
/* Tags are assumed to be of format nn or #nn in comment at end of line */
|
||||||
|
/* Used to determine default argument for tag question */
|
||||||
|
long highestRevision(vstring fileName);
|
||||||
|
|
||||||
|
|
||||||
|
/* Get numeric revision from the tag on a line (returns 0 if none) */
|
||||||
|
/* Tags are assumed to be of format nn or #nn in comment at end of line */
|
||||||
|
long getRevision(vstring line);
|
||||||
|
|
||||||
|
|
||||||
|
/* These two functions emulate 2 GOSUBs in BASIC, that are part of a
|
||||||
|
translation of a very old BASIC program (by nm) that implemented a
|
||||||
|
difference algorithm (like Unix diff). */
|
||||||
|
void gosub_7320(void);
|
||||||
|
void gosub_7330(void);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMWORD_H_ */
|
244
mmwtex.h
Normal file
244
mmwtex.h
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* Copyright (C) 2020 NORMAN MEGILL nm at alum.mit.edu */
|
||||||
|
/* License terms: GNU General Public License */
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*34567890123456 (79-character line to adjust editor window) 2345678901234567*/
|
||||||
|
|
||||||
|
#ifndef METAMATH_MMWTEX_H_
|
||||||
|
#define METAMATH_MMWTEX_H_
|
||||||
|
|
||||||
|
#include "mmvstr.h"
|
||||||
|
#include "mmdata.h"
|
||||||
|
|
||||||
|
/* Colors for HTML pages. */
|
||||||
|
#define GREEN_TITLE_COLOR "\"#006633\""
|
||||||
|
#define MINT_BACKGROUND_COLOR "\"#EEFFFA\""
|
||||||
|
#define PINK_NUMBER_COLOR "\"#FA8072\"" /* =salmon; was FF6666 */
|
||||||
|
#define PURPLISH_BIBLIO_COLOR "\"#FAEEFF\""
|
||||||
|
|
||||||
|
|
||||||
|
/* 29-Jul-2008 nm Sandbox stuff */
|
||||||
|
#define SANDBOX_COLOR "\"#FFFFD9\""
|
||||||
|
|
||||||
|
/* TeX flags */
|
||||||
|
/* 14-Sep-2010 nm Removed simpleTexFlag; added g_oldTexFlag */
|
||||||
|
extern flag g_oldTexFlag; /* Use macros in output; obsolete; take out someday */
|
||||||
|
|
||||||
|
/* HTML flags */
|
||||||
|
extern flag g_htmlFlag; /* HTML flag: 0 = TeX, 1 = HTML */
|
||||||
|
extern flag g_altHtmlFlag; /* Use "althtmldef" instead of "htmldef". This is
|
||||||
|
intended to allow the generation of pages with the old Symbol font
|
||||||
|
instead of the individual GIF files. */
|
||||||
|
extern flag g_briefHtmlFlag; /* Output statement only, for statement display
|
||||||
|
in other HTML pages, such as the Proof Explorer home page */
|
||||||
|
extern long g_extHtmlStmt; /* At this statement and above, use the exthtmlxxx
|
||||||
|
variables for title, links, etc. This was put in to allow proper
|
||||||
|
generation of the Hilbert Space Explorer extension to the set.mm
|
||||||
|
database. */
|
||||||
|
extern vstring g_extHtmlTitle; /* Title of extended section if any; set by
|
||||||
|
by exthtmltitle command in special $t comment of database source */
|
||||||
|
extern vstring g_htmlVarColor; /* Set by htmlvarcolor commands */
|
||||||
|
/* Added 26-Aug-2017 nm for use by mmcmds.c */
|
||||||
|
extern vstring g_htmlHome; /* Set by htmlhome command */
|
||||||
|
/* Added 10/13/02 for use in metamath.c bibliography cross-reference */
|
||||||
|
extern vstring g_htmlBibliography; /* Optional; set by htmlbibliography command */
|
||||||
|
extern vstring g_extHtmlBibliography; /* Optional; set by exthtmlbibliography
|
||||||
|
command */
|
||||||
|
extern vstring g_htmlCSS; /* Set by htmlcss commands */ /* 14-Jan-2016 nm */
|
||||||
|
/* Added 14-Jan-2016 */
|
||||||
|
extern vstring g_htmlFont; /* Optional; set by g_htmlFont command */
|
||||||
|
|
||||||
|
void eraseTexDefs(void); /* Undo readTexDefs() */
|
||||||
|
|
||||||
|
/* TeX/HTML/ALT_HTML word-processor-specific routines */
|
||||||
|
/* Returns 2 if there were severe parsing errors, 1 if there were warnings but
|
||||||
|
no errors, 0 if no errors or warnings */
|
||||||
|
flag readTexDefs(
|
||||||
|
flag errorsOnly, /* 1 = supprees non-error messages */
|
||||||
|
flag noGifCheck /* 1 = don't check for missing GIFs */);
|
||||||
|
|
||||||
|
extern flag g_texDefsRead;
|
||||||
|
struct texDef_struct { /* 27-Oct-2012 nm Made global for "erase" */
|
||||||
|
vstring tokenName; /* ASCII token */
|
||||||
|
vstring texEquiv; /* Converted to TeX */
|
||||||
|
};
|
||||||
|
extern struct texDef_struct *g_TexDefs; /* 27-Oct-2012 nm Now glob for "erase" */
|
||||||
|
|
||||||
|
|
||||||
|
long texDefWhiteSpaceLen(char *ptr);
|
||||||
|
long texDefTokenLen(char *ptr);
|
||||||
|
/* Token comparison for qsort */
|
||||||
|
int texSortCmp(const void *key1, const void *key2);
|
||||||
|
/* Token comparison for bsearch */
|
||||||
|
int texSrchCmp(const void *key, const void *data);
|
||||||
|
/* Convert ascii to a string of \tt tex */
|
||||||
|
/* (The caller must surround it by {\tt }) */
|
||||||
|
vstring asciiToTt(vstring s);
|
||||||
|
vstring tokenToTex(vstring mtoken, long statemNum);
|
||||||
|
/* Converts a comment section in math mode to TeX. Each math token
|
||||||
|
MUST be separated by white space. TeX "$" does not surround the output. */
|
||||||
|
vstring asciiMathToTex(vstring mathComment, long statemNum);
|
||||||
|
/* Gets the next section of a comment that is in the current mode (text,
|
||||||
|
label, or math). If 1st char. is not "$", text mode is assumed.
|
||||||
|
mode = 0 means end of comment reached. srcptr is left at 1st char.
|
||||||
|
of start of next comment section. */
|
||||||
|
vstring getCommentModeSection(vstring *srcptr, char *mode);
|
||||||
|
void printTexHeader(flag texHeaderFlag);
|
||||||
|
|
||||||
|
/* Prints an embedded comment in TeX. The commentPtr must point to the first
|
||||||
|
character after the "$(" in the comment. The printout ends when the first
|
||||||
|
"$)" or null character is encountered. commentPtr must not be a temporary
|
||||||
|
allocation. htmlCenterFlag, if 1, means to center the HTML and add a
|
||||||
|
"Description:" prefix.*/
|
||||||
|
/* void printTexComment(vstring commentPtr, char htmlCenterFlag); */
|
||||||
|
/* 17-Nov-2015 nm Added 3rd & 4th arguments; returns 1 if error/warning */
|
||||||
|
flag printTexComment(vstring commentPtr, /* Sends result to g_texFilePtr */
|
||||||
|
flag htmlCenterFlag, /* 1 = htmlCenterFlag */
|
||||||
|
long actionBits, /* see indicators below */
|
||||||
|
flag noFileCheck /* 1 = noFileCheck */);
|
||||||
|
/* Indicators for actionBits */
|
||||||
|
#define ERRORS_ONLY 1
|
||||||
|
#define PROCESS_SYMBOLS 2
|
||||||
|
#define PROCESS_LABELS 4
|
||||||
|
#define ADD_COLORED_LABEL_NUMBER 8
|
||||||
|
#define PROCESS_BIBREFS 16
|
||||||
|
#define PROCESS_UNDERSCORES 32
|
||||||
|
/* CONVERT_TO_HTML means '<' to '<'; unless <HTML> in comment (and strip it) */
|
||||||
|
#define CONVERT_TO_HTML 64
|
||||||
|
/* METAMATH_COMMENT means $) (as well as end-of-string) terminates string. */
|
||||||
|
#define METAMATH_COMMENT 128
|
||||||
|
/* PROCESS_ALL is for convenience */
|
||||||
|
#define PROCESS_EVERYTHING PROCESS_SYMBOLS + PROCESS_LABELS \
|
||||||
|
+ ADD_COLORED_LABEL_NUMBER + PROCESS_BIBREFS \
|
||||||
|
+ PROCESS_UNDERSCORES + CONVERT_TO_HTML + METAMATH_COMMENT
|
||||||
|
|
||||||
|
void printTexLongMath(nmbrString *proofStep, vstring startPrefix,
|
||||||
|
vstring contPrefix, long hypStmt, long indentationLevel);
|
||||||
|
void printTexTrailer(flag texHeaderFlag);
|
||||||
|
|
||||||
|
/* Added 4-Dec-03
|
||||||
|
Function implementing WRITE THEOREM_LIST / THEOREMS_PER_PAGE nn */
|
||||||
|
void writeTheoremList(long theoremsPerPage, flag showLemmas,
|
||||||
|
flag noVersioning);
|
||||||
|
|
||||||
|
#define HUGE_DECORATION "####"
|
||||||
|
#define BIG_DECORATION "#*#*"
|
||||||
|
#define SMALL_DECORATION "=-=-"
|
||||||
|
#define TINY_DECORATION "-.-."
|
||||||
|
|
||||||
|
/* 2-Aug-2009 nm - broke this function out from writeTheoremList() */
|
||||||
|
/* 20-Jun-2014 nm - added hugeHdrAddr */
|
||||||
|
/* 21-Aug-2017 nm - added tinyHdrAddr */
|
||||||
|
/* 6-Aug-2019 nm - changed return type from void to flag (=char) */
|
||||||
|
/* 24-Aug-2020 nm - added fineResolution */
|
||||||
|
/* 12-Sep-2020 nm - added fullComment */
|
||||||
|
flag getSectionHeadings(long stmt, vstring *hugeHdrTitle,
|
||||||
|
vstring *bigHdrTitle,
|
||||||
|
vstring *smallHdrTitle,
|
||||||
|
vstring *tinyHdrTitle,
|
||||||
|
/* Added 8-May-2015 nm */
|
||||||
|
vstring *hugeHdrComment,
|
||||||
|
vstring *bigHdrComment,
|
||||||
|
vstring *smallHdrComment,
|
||||||
|
vstring *tinyHdrComment,
|
||||||
|
/* Added 24-Aug-2020 nm */
|
||||||
|
flag fineResolution, /* 0 = consider just successive $a/$p, 1 = all stmts */
|
||||||
|
flag fullComment /* 1 = put $( + header + comment + $) into xxxHdrTitle */
|
||||||
|
);
|
||||||
|
|
||||||
|
/****** 15-Aug-2020 nm Obsolete
|
||||||
|
/@ TeX symbol dictionary @/
|
||||||
|
extern FILE @g_tex_dict_fp; /@ File pointers @/
|
||||||
|
extern vstring g_tex_dict_fn; /@ File names @/
|
||||||
|
******/
|
||||||
|
|
||||||
|
/* TeX normal output */
|
||||||
|
extern flag g_texFileOpenFlag;
|
||||||
|
extern FILE *g_texFilePtr;
|
||||||
|
|
||||||
|
/* Pink statement number for HTML pages */
|
||||||
|
/* 10/10/02 (This is no longer used?) */
|
||||||
|
/*
|
||||||
|
long pinkNumber(long statemNum);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Pink statement number HTML code for HTML pages - added 10/10/02 */
|
||||||
|
/* Warning: caller must deallocate returned string */
|
||||||
|
vstring pinkHTML(long statemNum);
|
||||||
|
|
||||||
|
/* Pink statement number range HTML code for HTML pages, separated by a
|
||||||
|
"-" - added 24-Aug-04 */
|
||||||
|
/* Warning: caller must deallocate returned string */
|
||||||
|
vstring pinkRangeHTML(long statemNum1, long statemNum2);
|
||||||
|
|
||||||
|
#define PINK_NBSP " " /* Either "" or " " depending on taste, it is
|
||||||
|
the separator between a statement href and its pink number */
|
||||||
|
|
||||||
|
/* 30-Jan-04 nm Comment out the following line to go back to the pink-only
|
||||||
|
color for the little statement numbers on the HTML pages */
|
||||||
|
#define RAINBOW_OPTION /* "Rainbow" instead of pink color for little numbers */
|
||||||
|
|
||||||
|
#ifdef RAINBOW_OPTION
|
||||||
|
/* This function converts a "spectrum" color (1 to maxColor) to an
|
||||||
|
RBG value in hex notation for HTML. The caller must deallocate the
|
||||||
|
returned vstring. color = 1 (red) to maxColor (violet). */
|
||||||
|
/* ndm 10-Jan-04 */
|
||||||
|
vstring spectrumToRGB(long color, long maxColor);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INDENT_HTML_PROOFS /* nm 3-Feb-04 - indentation experiment */
|
||||||
|
|
||||||
|
/* Added 20-Sep-03 (broken out of printTexLongMath() for better
|
||||||
|
modularization) */
|
||||||
|
/* Returns the HTML code for GIFs (!g_altHtmlFlag) or Unicode (g_altHtmlFlag),
|
||||||
|
or LaTeX when !g_htmlFlag, for the math string (hypothesis or conclusion) that
|
||||||
|
is passed in. */
|
||||||
|
/* Warning: The caller must deallocate the returned vstring. */
|
||||||
|
vstring getTexLongMath(nmbrString *mathString, long statemNum);
|
||||||
|
|
||||||
|
/* Added 18-Sep-03 (transferred from metamath.c) */
|
||||||
|
/* Returns the TeX, or HTML code for GIFs (!g_altHtmlFlag) or Unicode
|
||||||
|
(g_altHtmlFlag), for a statement's hypotheses and assertion in the form
|
||||||
|
hyp & ... & hyp => assertion */
|
||||||
|
/* Warning: The caller must deallocate the returned vstring. */
|
||||||
|
/* 14-Sep-2010 nm Changed name from getHTMLHypAndAssertion() */
|
||||||
|
vstring getTexOrHtmlHypAndAssertion(long statemNum);
|
||||||
|
|
||||||
|
/* Added 17-Nov-2015 (broken out of metamath.c for better modularization) */
|
||||||
|
/* For WRITE BIBLIOGRAPHY command and error checking by VERIFY MARKUP */
|
||||||
|
/* Returns 0 if OK, 1 if error or warning found */
|
||||||
|
flag writeBibliography(vstring bibFile,
|
||||||
|
vstring labelMatch, /* Normally "*" except by verifyMarkup() */
|
||||||
|
flag errorsOnly, /* 1 = no output, just warning msgs if any */
|
||||||
|
flag noFileCheck); /* 1 = ignore missing external files (gifs, bib, etc.) */
|
||||||
|
|
||||||
|
/* 5-Aug-2020 nm */
|
||||||
|
/* Globals to hold mathbox information. They should be re-initialized
|
||||||
|
by the ERASE command (eraseSource()). g_mathboxStmt = 0 indicates
|
||||||
|
it and the other variables haven't been initialized. */
|
||||||
|
extern long g_mathboxStmt; /* stmt# of "mathbox" label; statements+1 if none */
|
||||||
|
extern long g_mathboxes; /* # of mathboxes */
|
||||||
|
/* The following 3 "strings" are 0-based e.g. g_mathboxStart[0] is for
|
||||||
|
mathbox #1 */
|
||||||
|
extern nmbrString *g_mathboxStart; /* Start stmt vs. mathbox # */
|
||||||
|
extern nmbrString *g_mathboxEnd; /* End stmt vs. mathbox # */
|
||||||
|
extern pntrString *g_mathboxUser; /* User name vs. mathbox # */
|
||||||
|
|
||||||
|
/* 5-Aug-2020 nm */
|
||||||
|
/* Returns 1 if statements are in different mathboxes */
|
||||||
|
flag inDiffMathboxes(long stmt1, long stmt2);
|
||||||
|
/* Returns the user of the mathbox that a statement is in, or ""
|
||||||
|
if the statement is not in a mathbox. */
|
||||||
|
/* Caller should NOT deallocate returned string (it points directly to
|
||||||
|
g_mathboxUser[] entry); use directly in print2() messages */
|
||||||
|
vstring getMathboxUser(long stmt);
|
||||||
|
/* Returns the mathbox number (starting at 1) that stmt is in, or 0 if not
|
||||||
|
in a mathbox */
|
||||||
|
long getMathboxNum(long stmt);
|
||||||
|
/* Populates mathbox information */
|
||||||
|
void assignMathboxInfo(void);
|
||||||
|
/* Creates lists of mathbox starts and user names */
|
||||||
|
long getMathboxLoc(nmbrString **mathboxStart, nmbrString **mathboxEnd,
|
||||||
|
pntrString **mathboxUser);
|
||||||
|
|
||||||
|
#endif /* METAMATH_MMWTEX_H_ */
|
864
peano.mm
Normal file
864
peano.mm
Normal file
@ -0,0 +1,864 @@
|
|||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
Metamath source file: axioms for Peano arithmetic
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( Copyright (GPL) 2004 Robert Solovay, PO Box 5949, Eugene OR, 97405 $)
|
||||||
|
$( Comments welcome; email to: solovay at gmail dot com $)
|
||||||
|
|
||||||
|
$( Version of 22-Jun-2021 $)
|
||||||
|
$( Replaces prior version of 13-July-04 $)
|
||||||
|
$( 22-Jun-2021 (Patrick Brosnan) - Add missing distinct variable constraints
|
||||||
|
to pa_ax7 $)
|
||||||
|
$( 7-Oct-2004 (N. Megill) - Minor fixes to conform to strict Metamath spec $)
|
||||||
|
$( 11-Oct-2004 (N. Megill) - "$a implies" --> "$a |- implies" at line 224 $)
|
||||||
|
$( 24-Jun-2006 (N. Megill) - Made label and math symbol names spaces
|
||||||
|
disjoint, as required by the 24-Jun-2006 modification of the Metamath
|
||||||
|
specification. Specifically, the labels binop, logbinop, binpred,
|
||||||
|
and quant were changed to binop_, logbinop_, binpred_, and quant_
|
||||||
|
respectively. $)
|
||||||
|
$( 11-Nov-2014 (N. Megill) - updated R. Solovay's email address $)
|
||||||
|
|
||||||
|
$( This file is a mixture of two sorts of things:
|
||||||
|
|
||||||
|
1) Formal metamath axioms and supporting material. [$f and $d
|
||||||
|
statements for example.]
|
||||||
|
|
||||||
|
2) Informal metamathematical arguments that show our axioms suffice to
|
||||||
|
"do Peano in metamath".
|
||||||
|
|
||||||
|
All our metamathematical arguments are quite constructive and
|
||||||
|
certainly could be formalized in Primitive Recursive Arithmetic. $)
|
||||||
|
|
||||||
|
$( We shall slightly deviate from the treatment in Appendix C of the
|
||||||
|
metamath book. We assume that for each constant c an infinite subset
|
||||||
|
of the variables is preassigned to that constant.
|
||||||
|
|
||||||
|
In particular we will have a constant var. Among our other constants
|
||||||
|
will be all the symbols of Peano arithmetic except the variables. The
|
||||||
|
variables of the formal language of Peano Arithmetic will be
|
||||||
|
identified with the variables attached to the constant symbol var. In
|
||||||
|
this way each well formed formula or term of PA will *be* a certan
|
||||||
|
metamath expression. $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
Syntax
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$c |- wff term var $.
|
||||||
|
|
||||||
|
$( The next set of axioms will give the inductive definition of
|
||||||
|
terms. We will be using Polish notation in our formal development of
|
||||||
|
the syntax of PA. $)
|
||||||
|
|
||||||
|
$v s t u s0 s1 t0 t1 $.
|
||||||
|
|
||||||
|
ts $f term s $.
|
||||||
|
tt $f term t $.
|
||||||
|
tu $f term u $.
|
||||||
|
ts0 $f term s0 $.
|
||||||
|
ts1 $f term s1 $.
|
||||||
|
tt0 $f term t0 $.
|
||||||
|
tt1 $f term t1 $.
|
||||||
|
|
||||||
|
$v v x y z $.
|
||||||
|
varv $f var v $.
|
||||||
|
varx $f var x $.
|
||||||
|
vary $f var y $.
|
||||||
|
varz $f var z $.
|
||||||
|
|
||||||
|
$c 0 S + * $.
|
||||||
|
|
||||||
|
$( It is often possible to treat + and * in parallel. The following
|
||||||
|
device allows us to do this. $)
|
||||||
|
|
||||||
|
$c BINOP $.
|
||||||
|
$v binop $.
|
||||||
|
binop_ $f BINOP binop $.
|
||||||
|
binop_plus $a BINOP + $.
|
||||||
|
binop_times $a BINOP * $.
|
||||||
|
|
||||||
|
tvar $a term v $.
|
||||||
|
tzero $a term 0 $.
|
||||||
|
tsucc $a term S s $.
|
||||||
|
tbinop $a term binop s t $.
|
||||||
|
|
||||||
|
$( The next set of axioms will give the inductive definition of wff $)
|
||||||
|
|
||||||
|
$c not or and implies iff $.
|
||||||
|
$c LOGBINOP $.
|
||||||
|
$v logbinop $.
|
||||||
|
logbinop_ $f LOGBINOP logbinop $.
|
||||||
|
logbinopor $a LOGBINOP or $.
|
||||||
|
logbinopand $a LOGBINOP and $.
|
||||||
|
logbinopimplies $a LOGBINOP implies $.
|
||||||
|
logbinopiff $a LOGBINOP iff $.
|
||||||
|
|
||||||
|
$c = < $.
|
||||||
|
$c BINPRED $.
|
||||||
|
$v binpred $.
|
||||||
|
binpred_ $f BINPRED binpred $.
|
||||||
|
binpred_equals $a BINPRED = $.
|
||||||
|
binpred_less_than $a BINPRED < $.
|
||||||
|
|
||||||
|
$c forall exists $.
|
||||||
|
$c QUANT $.
|
||||||
|
$v quant $.
|
||||||
|
quant_ $f QUANT quant $.
|
||||||
|
quant_all $a QUANT forall $.
|
||||||
|
quant_ex $a QUANT exists $.
|
||||||
|
|
||||||
|
$v phi psi chi $.
|
||||||
|
wff_phi $f wff phi $.
|
||||||
|
wff_psi $f wff psi $.
|
||||||
|
wff-chi $f wff chi $.
|
||||||
|
|
||||||
|
wff_atom $a wff binpred s t $.
|
||||||
|
wff_not $a wff not psi $.
|
||||||
|
wff_logbinop $a wff logbinop psi phi $.
|
||||||
|
wff_quant $a wff quant v phi $.
|
||||||
|
|
||||||
|
$( This completes our description of the syntactic categories of wff
|
||||||
|
and term $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
"Correct" axioms
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( In the various sections of this file we will be adding various
|
||||||
|
axioms [$a statements]. The crucial correctness property that they
|
||||||
|
will have is the following:
|
||||||
|
|
||||||
|
Consider a substitution instance of the axiom such that the only
|
||||||
|
variables remaining in the instance [in either hypothesis or
|
||||||
|
conclusion] are of type var. Then if all the hypotheses [$e
|
||||||
|
statements] have the form
|
||||||
|
|- phi
|
||||||
|
[where phi is a theorem of PA] then the conclusion is also a
|
||||||
|
theorem of PA.
|
||||||
|
|
||||||
|
The verification that the various axioms we add are correct in
|
||||||
|
this sense will be "left to the reader". Usually the proof that I
|
||||||
|
have in mind is a semantic one based upon the consideration of
|
||||||
|
models of PA. $)
|
||||||
|
$( I will give a discussion at the end of this document as to why
|
||||||
|
sticking with this correctness condition on axioms suffices to
|
||||||
|
guarantee that only correct theorems of Peano arithmetic are
|
||||||
|
proved.
|
||||||
|
$)
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
Propositional logic
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( We follow closely the treatment in set.mm. We do have to change the
|
||||||
|
axioms "into Polish". $)
|
||||||
|
|
||||||
|
ax-1 $a |- implies phi implies psi phi $.
|
||||||
|
|
||||||
|
ax-2 $a |- implies
|
||||||
|
implies phi implies psi chi
|
||||||
|
implies
|
||||||
|
implies phi psi
|
||||||
|
implies phi chi $.
|
||||||
|
ax-3 $a |- implies
|
||||||
|
implies not phi not psi
|
||||||
|
implies psi phi $.
|
||||||
|
|
||||||
|
$( Modus ponens: $)
|
||||||
|
${
|
||||||
|
min $e |- phi $.
|
||||||
|
maj $e |- implies phi psi $.
|
||||||
|
ax-mp $a |- psi $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
bi1 $a |- implies
|
||||||
|
iff phi psi
|
||||||
|
implies phi psi $.
|
||||||
|
bi2 $a |- implies
|
||||||
|
iff phi psi
|
||||||
|
implies psi phi $.
|
||||||
|
bi3 $a |- implies
|
||||||
|
implies phi psi
|
||||||
|
implies
|
||||||
|
implies psi phi
|
||||||
|
iff phi psi $.
|
||||||
|
df-an $a |- iff
|
||||||
|
and phi psi
|
||||||
|
not implies phi not psi $.
|
||||||
|
df-or $a |- iff
|
||||||
|
or phi psi
|
||||||
|
implies not phi psi $.
|
||||||
|
|
||||||
|
$( Equality axioms $)
|
||||||
|
|
||||||
|
$( From here on out, I won't make an effort to cordinate labels
|
||||||
|
between my axioms and those of set.mm $)
|
||||||
|
|
||||||
|
eq-refl $a |- = t t $.
|
||||||
|
eq-sym $a |- implies = s t = t s $.
|
||||||
|
eq-trans $a |- implies
|
||||||
|
and = s t = t u
|
||||||
|
= s u $.
|
||||||
|
eq-congr $a |- implies
|
||||||
|
and = s0 s1 = t0 t1
|
||||||
|
iff binpred s0 t0 binpred s1 t1 $.
|
||||||
|
|
||||||
|
$( The next two axioms were missing in the previous draft of
|
||||||
|
peano.mm. They are definitely needed. $)
|
||||||
|
|
||||||
|
eq-suc $a |- implies
|
||||||
|
= s t
|
||||||
|
= S s S t $.
|
||||||
|
eq-binop $a |- implies
|
||||||
|
and = s0 s1 = t0 t1
|
||||||
|
= binop s0 t0 binop s1 t1 $.
|
||||||
|
|
||||||
|
$( Lemma 1 $)
|
||||||
|
|
||||||
|
$( Lemma 1 of the 2004 version of this document was not needed in the
|
||||||
|
subsequent development and has been deleted. I decided not to change
|
||||||
|
the numbering of subsequent lemmas. $)
|
||||||
|
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
Free and bound variables; alpha equivalence
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( It will be useful to warm up with some familiar concepts. Let PHI
|
||||||
|
be a well-formed formula of Peano arithmetic. Then Phi is a finite
|
||||||
|
sequence of symbols, s_1 ... s_n.
|
||||||
|
|
||||||
|
Following Shoenfield's treatment in "Mathematical Logic" we use the
|
||||||
|
term "designator" for a sequence of symbols that is either a term
|
||||||
|
or a wff. A basic result says that each s_i is the initial symbol
|
||||||
|
of precisely one subsequence of s_1 ... s_n which is a designator.
|
||||||
|
|
||||||
|
Suppose that s_i is a variable. We say that s_i is bound in PHI if
|
||||||
|
there is a subformula of PHI containing s_i whose initial symbol is
|
||||||
|
a quantifier and whose second symbol is the same variable as s_i.
|
||||||
|
|
||||||
|
[Otherwise s_i is *free* in PHI.]
|
||||||
|
|
||||||
|
If s_i is a bound variable, then there is a shortest subformula of
|
||||||
|
PHI in which s_i is bound. The quantifier beginning this subformula
|
||||||
|
is the quantifier that *binds* s_i. $)
|
||||||
|
|
||||||
|
$( alpha equivalence $)
|
||||||
|
|
||||||
|
$( Let Phi_1 and Phi_2 be well-formed formulas of PA. Say Phi_1 is s_1
|
||||||
|
... s_n and Phi_2 is t_1 ... t_m.
|
||||||
|
|
||||||
|
We say that Phi_1 and Phi_2 are alpha-equialent if:
|
||||||
|
|
||||||
|
1) n = m.
|
||||||
|
|
||||||
|
2) Let 1 <= i <= n. Then s_i is a constant iff t_i is; in that case,
|
||||||
|
they are the *same* constant.
|
||||||
|
|
||||||
|
3) Let 1 <= i <= n. Suppose that s_i is a variable. [So t_i is a
|
||||||
|
variable as well.] Then s_i is free in Phi_1 iff t_i is free in
|
||||||
|
Phi_2. If s_i is free in Phi_1, then s_i = t_i.
|
||||||
|
|
||||||
|
4) Let 1 <= i <= n. Suppose that s_i is a variable that is bound in
|
||||||
|
Phi_1. [It follows that t_i is a variable that is bound in Phi_2.]
|
||||||
|
Let s_j be the quantifier that binds s_i. Then t_j is the
|
||||||
|
quantifier that binds t_i.
|
||||||
|
|
||||||
|
[This ends the definition of alpha-equivalence.]
|
||||||
|
|
||||||
|
It is indeed true that alpha-equivalence is an equivalence relation.
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( Trim formulas $)
|
||||||
|
|
||||||
|
$( The following concept is non-standard. A well-formed formula of PA
|
||||||
|
is *trim* if:
|
||||||
|
|
||||||
|
1) No variable occurs both free and bound in Phi.
|
||||||
|
|
||||||
|
2) Distinct quantifiers bind distinct variables.
|
||||||
|
|
||||||
|
[So
|
||||||
|
exists x exists x = x x
|
||||||
|
is not trim since the two quantifiers both bind the variable x.]
|
||||||
|
|
||||||
|
Clearly every formula is alpha-equivalent to some trim
|
||||||
|
formula. Moreover, we can assume that the bound variables of this
|
||||||
|
trim equivalent avoid some specified finite set of variables.
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( Here is the next Lemma we are heading toward. We can add a finite
|
||||||
|
number of correct axioms to our file so that once this is done, if
|
||||||
|
Phi_1 and Phi_2 are alpha-equivalent formulas then [subject to the
|
||||||
|
requirement that any pair of distinct variables appearing in Phi_1 or
|
||||||
|
Phi_2 is declared disjoint]
|
||||||
|
|
||||||
|
|- iff Phi_1 Phi_2
|
||||||
|
is a theorem of Metmath [i.e. follows from the given axioms].
|
||||||
|
|
||||||
|
In view of the remarks about trim formulas, we are reduced to the
|
||||||
|
following special case: Phi_2 is trim and no bound variable of Phi_2
|
||||||
|
appears [free or bound] in Phi_1.
|
||||||
|
|
||||||
|
We fix Phi_1 and Phi_2 subject to this restriction. We will develop
|
||||||
|
the axioms we need in the course of the proof. Of course, the reader
|
||||||
|
should verify that we could have specified them in advance. In
|
||||||
|
particular the additional axioms we list will not depend on Phi_1 or Phi_2. $)
|
||||||
|
|
||||||
|
$( Our proof strategy is as follows;
|
||||||
|
|
||||||
|
To each subformula Psi of Phi_1, we shall attach a claim C(Psi) [which
|
||||||
|
will also be a well-formed formula of PA]. We will prove in Metamath
|
||||||
|
the various claims C(Psi). The construction of these proofs will be an
|
||||||
|
inductive one [by induction on the length of the subformula,
|
||||||
|
say]. From the claim C(Phi_1), the desired equivalence of Phi_1 and
|
||||||
|
Phi_2 will easily follow. $)
|
||||||
|
|
||||||
|
$( Weak alpha-equivalence $)
|
||||||
|
|
||||||
|
$( Before describing the claims C(Psi), I need to introduce the notion
|
||||||
|
of weak alpha-equivalence. Let Psi_1 and Psi_2 be two well-formed
|
||||||
|
formulas of PA.
|
||||||
|
|
||||||
|
Say Psi_1 is s_1 ... s_m and Psi_2 is t_1 ... t_n.
|
||||||
|
|
||||||
|
Then Psi_1 and Psi_2 are weakly alpha equivalent iff:
|
||||||
|
|
||||||
|
1) m = n;
|
||||||
|
|
||||||
|
2) Let 1 <= i <= n. Then s_i is a constant iff t_i is; in that case,
|
||||||
|
they are the *same* constant.
|
||||||
|
|
||||||
|
3) Let 1 <= i <= n. Suppose that s_i is a variable. [So t_i is a
|
||||||
|
variable as well.] Then s_i is free in Psi_1 iff t_i is free in
|
||||||
|
Psi_2.
|
||||||
|
|
||||||
|
3a) Let 1 <= i < j <= n. Suppose that s_i and s_j are variables free
|
||||||
|
in Psi_1. [It follows that t_i and t_j are free variables in Psi_2.]
|
||||||
|
Then s_i = s_j iff t_i = t_j.
|
||||||
|
|
||||||
|
4) Let 1 <= i <= n. Suppose that s_i is a variable that is bound in
|
||||||
|
Psi_1. [It follows that t_i is a variable that is bound in Psi_2.]
|
||||||
|
Let s_j be the quantifier that binds s_i. Then t_j is the
|
||||||
|
quantifier that binds t_i.
|
||||||
|
|
||||||
|
[This ends the definition of weak alpha-equivalence.] $)
|
||||||
|
|
||||||
|
$( I need a pedantic fact:
|
||||||
|
|
||||||
|
Proposition 2.1. Let Phi_1 = s_1,..., s_m and Phi_2 = t_1...t_m be
|
||||||
|
as above. Let 1 <= i <= j <= m. Then s_i ... s_j is a term
|
||||||
|
[formula] iff t_i ... t_j is.
|
||||||
|
|
||||||
|
The proof is by induction on j - i and is straightforward. [It
|
||||||
|
splits into cases according to what s_i is.] $)
|
||||||
|
|
||||||
|
$( The following explains the importance of "weak alpha equivalence":
|
||||||
|
|
||||||
|
Proposition 2.2.
|
||||||
|
Let Psi_1 be a subformula of Phi_1, and Psi_2 the corresponding
|
||||||
|
subformula of Phi_2. (Cf. the "pedantic fact" just above.) Then
|
||||||
|
Psi_1 and Psi_2 are weakly alpha equivalent.
|
||||||
|
|
||||||
|
Only clause 3a) of the definition of weak alpha equivalence
|
||||||
|
requires discussion:
|
||||||
|
|
||||||
|
Say Psi_1 occupies positions i ... j of Phi_1. Let i <= a < b <= j
|
||||||
|
and let s_a and s_b be the same variable x. We suppose that s_a and
|
||||||
|
s_b are free in Psi_1. We shall show that t_a = t_b. {This will
|
||||||
|
prove one direction of the iff; the other direction is proved
|
||||||
|
similarly.}
|
||||||
|
|
||||||
|
If s_a and s_b are both free in Phi_1 then our claim is clear since
|
||||||
|
Phi_1 and Phi_2 are alpha equivalent. If not, let Theta_1 be the
|
||||||
|
smallest subformula of Phi_1 in which one of s_a and s_b is
|
||||||
|
bound. Then both s_a and s_b are bound by the quantifer that begins
|
||||||
|
Theta_1.
|
||||||
|
|
||||||
|
Let Theta_2 be the subformula of Phi_2 that corresponds to
|
||||||
|
Theta_1. Using the alpha equivalence of Phi_1 and Phi_2 we see that
|
||||||
|
both t_a and t_b are bound by the quantifer that begins
|
||||||
|
Theta_2. Hence t_a = t_b.
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( We are now able to begin the definition of C(Psi_1) for Psi_1 a
|
||||||
|
subformula of Phi_1. It will have the form
|
||||||
|
|
||||||
|
implies H(Psi_1)
|
||||||
|
iff Psi_1 Psi_2
|
||||||
|
|
||||||
|
where Psi_2 is the subformula of Phi_2 that corresponds to Psi_1.
|
||||||
|
|
||||||
|
It remains to describe H(Psi_1):
|
||||||
|
|
||||||
|
Let w be a variable that does not appear [free or bound] in either
|
||||||
|
Phi_1 or Phi_2. Let x_1 ... x_r be the free variables appearing in
|
||||||
|
Psi_1 [listed without repetitions]. Because Psi_1 is weakly alpha
|
||||||
|
equivalent to Psi_2, we can define a bijection between the free
|
||||||
|
variables of Psi_1 and those of Psi_2 thus. If x_i appears freely in
|
||||||
|
position j of Psi_1 then the corresponding free variable of Psi_2,
|
||||||
|
say y_i, appears in position j of Psi_2.
|
||||||
|
|
||||||
|
H(Psi_1) is the conjunction of the following equalities:
|
||||||
|
|
||||||
|
1) = w w ;
|
||||||
|
|
||||||
|
2) = x_i y_i (for i = 1 ... r).
|
||||||
|
|
||||||
|
This completes our description of C(Psi_1). $)
|
||||||
|
|
||||||
|
$( Consider first C(Phi_1). Because Phi_1 is alpha equivalent to
|
||||||
|
Phi_2, H(Phi_1) is the conjunction of equalities of the form = a a .
|
||||||
|
Hence Metamath can prove H(Phi_1) and can see that C(Phi_1) is
|
||||||
|
equivalent to the equivalence:
|
||||||
|
|
||||||
|
iff Phi_1 Phi_2
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( So it will be sufficient to see that Metamath [after enrichment with
|
||||||
|
some additional correct axioms] can prove C(Psi_1) for every
|
||||||
|
subformula Psi_1 of Phi_1. The proof of this proceeds by induction on
|
||||||
|
the length of Psi_1.
|
||||||
|
|
||||||
|
If Psi_1 is atomic, our claim is easily proved using the equality
|
||||||
|
axioms.
|
||||||
|
|
||||||
|
The cases when Psi_1 is built up from smaller formulas using propositional
|
||||||
|
connectives are easily handled since Metamath knows propositional
|
||||||
|
logic.
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( It remains to consider the case when Psi_1 has the form Q x Chi_1
|
||||||
|
where Q is a quantifier.
|
||||||
|
|
||||||
|
It is clear that Psi_2 has the form Q y Chi_2 [where Chi_2 is the
|
||||||
|
subformula of Phi_2 that corresponds to Chi_1]. We will consider two
|
||||||
|
cases;
|
||||||
|
|
||||||
|
Case A: x = y;
|
||||||
|
|
||||||
|
Case B: x != y. $)
|
||||||
|
|
||||||
|
$( To handle Case A we adjoin the following axiom [which the reader
|
||||||
|
should verify is correct]. $)
|
||||||
|
|
||||||
|
${ $d phi x $.
|
||||||
|
alpha_hyp1 $e |- implies phi
|
||||||
|
iff psi chi $.
|
||||||
|
alpha_1 $a |- implies phi
|
||||||
|
iff quant x psi
|
||||||
|
quant x chi $. $}
|
||||||
|
|
||||||
|
$( We apply this axiom with H(Psi_1) in the role of phi and Q in the
|
||||||
|
role of quant. Chi_1 is in the role of psi and Chi_2 is in the role of
|
||||||
|
chi.
|
||||||
|
|
||||||
|
To see that the needed instance of alpha_hyp1 holds, note that
|
||||||
|
H(Chi_1) is either H(Psi_1) [up to a possible rearrangement of
|
||||||
|
conjuncts] or the conjunction of H(Psi_1) with the conjunct
|
||||||
|
= x x
|
||||||
|
|
||||||
|
So our needed instance follows from C(Chi_1), equality axioms and
|
||||||
|
propositional logic $)
|
||||||
|
|
||||||
|
$( We turn to case B. It is worthwhile to remind the reader that Phi_2
|
||||||
|
has been chosen so that no bound variable of Phi_2 appears either free
|
||||||
|
or bound in Phi_1.
|
||||||
|
|
||||||
|
Proposition 2.3. y does not appear [free or bound] in Psi_1. x does
|
||||||
|
not appear [free or bound] in Psi_2.
|
||||||
|
|
||||||
|
Proof: y appears bound in Psi_2. Hence it doesn't even appear [free or
|
||||||
|
bound] in Phi_1.
|
||||||
|
|
||||||
|
Suppose that x appears in Psi_2. Then this appearence must be free in
|
||||||
|
Phi_2. {Otherwise, x would not appear in Phi_1 but it is the second
|
||||||
|
symbol of Psi_1.} So at the same spot in Psi_1 x also appears, and
|
||||||
|
this occurrence is free in Phi_1. {This follows from the fact that
|
||||||
|
Phi_1 and Phi_2 are alpha equivalent.} But clearly this occurrence of
|
||||||
|
x in Psi_1 will be bound by the quantifier that starts
|
||||||
|
Psi_1. Contradiction! $)
|
||||||
|
|
||||||
|
$( Proposition 2.3 has the following immediate consequence:
|
||||||
|
|
||||||
|
Proposition 2.4: Neither of the variables x or y occurs in H(Psi_1).
|
||||||
|
|
||||||
|
Also it is easy to check that [up to propositional logic]
|
||||||
|
H(Chi_1) is either H(Psi_1) or the conjunction of H(Psi_1)
|
||||||
|
with
|
||||||
|
= x y
|
||||||
|
|
||||||
|
It follows that from C(Chi_1) one can deduce [using propositonal
|
||||||
|
logic] the following:
|
||||||
|
|
||||||
|
(A) implies H(Psi_1)
|
||||||
|
implies = x y
|
||||||
|
iff Chi_1 Chi_2 $)
|
||||||
|
|
||||||
|
$( Next we introduce the following Metamath axiom [which the reader
|
||||||
|
should verify is correct] $)
|
||||||
|
|
||||||
|
${ $d phi x $.
|
||||||
|
|
||||||
|
alpha_hyp2 $e |- implies phi chi $.
|
||||||
|
alpha_2 $a |- implies phi forall x chi $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( Using this axiom we can deduce from (A) and Proposition 2.4
|
||||||
|
the following:
|
||||||
|
|
||||||
|
(B) implies H(Psi_1)
|
||||||
|
forall x forall y implies = x y
|
||||||
|
iff Chi_1 Chi_2
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( We need to introduce another axiom [which the reader should verify
|
||||||
|
is correct] $)
|
||||||
|
|
||||||
|
${ $d phi y $.
|
||||||
|
$d psi x $.
|
||||||
|
$d x y $.
|
||||||
|
alpha_3 $a |- implies forall x forall y implies = x y
|
||||||
|
iff phi psi
|
||||||
|
iff quant x phi quant y psi $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( From this axiom, (B) and Proposition 2.3 we easily deduce:
|
||||||
|
|
||||||
|
(C) implies H(Psi_1)
|
||||||
|
iff Psi_1 Psi_2
|
||||||
|
|
||||||
|
which is C(Psi_1) $)
|
||||||
|
|
||||||
|
$( The following lemma should now be clear to the reader:
|
||||||
|
|
||||||
|
Lemma 2. Let Phi and Phi* be alpha equivalent formulas of PA. Then
|
||||||
|
using the axioms so far introduced, we can prove in Metamath the
|
||||||
|
sequence
|
||||||
|
|
||||||
|
|- iff Phi_1 Phi_2
|
||||||
|
|
||||||
|
from the disjointness assumption that all the distinct variables
|
||||||
|
appearing in Phi_1 or Phi_2 are asserted to be distinct in a $d
|
||||||
|
assumption. $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
Axioms and inference rules of predicate logic
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( Our next task is to prove the rule of inference and the axiom
|
||||||
|
associated to the "forall" quantifier. $)
|
||||||
|
|
||||||
|
$( Let's start with the rule of inference. We have to show that if
|
||||||
|
|
||||||
|
|- implies phi chi
|
||||||
|
|
||||||
|
and phi does not contain x free then also
|
||||||
|
|
||||||
|
|- implies phi forall x chi.
|
||||||
|
|
||||||
|
But this is easy. In view of what we have just shown, it is ok to
|
||||||
|
replace phi by an alpha-equivalent formula that does not contain x
|
||||||
|
at all. {In both our hypothesis and conclusion.}
|
||||||
|
|
||||||
|
But then we just need to invoke the axiom alpha_2. $)
|
||||||
|
|
||||||
|
$( We now turn to the axiom of "forall elimination". To state it we
|
||||||
|
introduce the familiar notion of substituting a term for the free
|
||||||
|
occurrences of a variable. So let phi be a formula, x a variable and t
|
||||||
|
a term. By phi[t/x] we mean the formula obtained by simultaneously
|
||||||
|
replacing each free occurrence of x in phi by a copy of the term t. {A
|
||||||
|
more rigorous definition would proceed by induction on the structure
|
||||||
|
of phi.}
|
||||||
|
|
||||||
|
We say that t is substitutable for x at the free occurrence of x in
|
||||||
|
phi [or just "substitutable" if we are being terse] if no variable
|
||||||
|
occuring in t falls under the scope of any quantifer of
|
||||||
|
phi. {Again, I am presuming this notion known; otherwise, I'd be
|
||||||
|
more careful with this definition.}
|
||||||
|
|
||||||
|
The final group of axioms of predicate calculus that we need to
|
||||||
|
derive have the following form:
|
||||||
|
|
||||||
|
(*) implies
|
||||||
|
forall x phi
|
||||||
|
phi[t/x]
|
||||||
|
|
||||||
|
**where** t is substitutable for x in phi.
|
||||||
|
|
||||||
|
Our next step is to show that it suffices to prove the following
|
||||||
|
special case of this axiom. phi x and t satisfy the following three
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
|
||||||
|
(1) The variable x does not appear in the term t.
|
||||||
|
|
||||||
|
(2) No bound variable of phi appears in t.
|
||||||
|
|
||||||
|
(3) The variable x does not appear bound in phi.
|
||||||
|
|
||||||
|
We can see this as follows. We can clearly find a formula
|
||||||
|
forall y psi
|
||||||
|
which is alpha equivalent to forall x phi such that:
|
||||||
|
(1') The variable y does not appear in the term t;
|
||||||
|
(2') No bound variable of psi appears in t;
|
||||||
|
(3') The variable y does not appear bound in psi.
|
||||||
|
|
||||||
|
Using the fact that t is substitutable for x in phi we easily see that
|
||||||
|
phi[t/x] is alpha equivalent to psi[t/y]. It follows that (*) is
|
||||||
|
alpha-equivalent to:
|
||||||
|
(**) implies
|
||||||
|
forall y psi
|
||||||
|
psi[t/y]
|
||||||
|
|
||||||
|
Hence Metamath can prove the equivalence of (*) and (**). But in view
|
||||||
|
of (1') through (3'), the instance (**) of for all elimination meets
|
||||||
|
our additional requirements (1) through (3).
|
||||||
|
|
||||||
|
In the remainder of our discussion we shall assume then that phi, x
|
||||||
|
and t meet the requirements (1) through (3). Note that it follows from
|
||||||
|
(2) that t is substitutable for x in phi.
|
||||||
|
|
||||||
|
[N.B. We cannot assume that the variables appearing in t do not appear
|
||||||
|
in phi.]
|
||||||
|
|
||||||
|
Here is the key idea of our approach: The formula phi[t/x] (under the
|
||||||
|
hypotheses (1) -- (3) just given) is equivalent to:
|
||||||
|
|
||||||
|
forall x implies
|
||||||
|
= x t
|
||||||
|
phi
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( We start by adding the following [correct!] axiom $)
|
||||||
|
|
||||||
|
${ $d x t $.
|
||||||
|
all_elim $a |- implies
|
||||||
|
forall x phi
|
||||||
|
forall x implies
|
||||||
|
= x t
|
||||||
|
phi $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( Using this axiom we can reduce our proof that Metamath proves all
|
||||||
|
instances of "all elimination" to the following lemma:
|
||||||
|
|
||||||
|
Lemma 3. Let t be a term of PA and phi a formula of PA. We assume:
|
||||||
|
1) The variable x does not occur in t;
|
||||||
|
2) No bound variable of phi appears in t.
|
||||||
|
3) The variable x does not occur bound in phi.
|
||||||
|
|
||||||
|
Then [after adding finitely many additional correct axioms whose
|
||||||
|
choice does not depend on phi] we can prove in Metamath:
|
||||||
|
|
||||||
|
|- iff
|
||||||
|
forall x implies
|
||||||
|
= x t
|
||||||
|
phi
|
||||||
|
phi[t/x]
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( We shall need a preliminary result:
|
||||||
|
|
||||||
|
Proposition 3.1 Let phi t and x obey our standing hypotheses 1) --
|
||||||
|
3). Let psi be a subformula of phi.
|
||||||
|
|
||||||
|
Then [after adding finitely many additional correct axioms whose
|
||||||
|
choice does not depend on phi] we can prove in Metamath:
|
||||||
|
|
||||||
|
|- implies = x t
|
||||||
|
iff psi psi[t/x]
|
||||||
|
|
||||||
|
The construction of such proofs [like many previous arguments] is by
|
||||||
|
induction on the tree of subformulas of phi. $)
|
||||||
|
|
||||||
|
$( The first case is when psi is atomic. This case is easily handled
|
||||||
|
using the equality axioms.
|
||||||
|
|
||||||
|
The second case is when the principal connective of psi is a
|
||||||
|
propositional connective. This case follows easily using propositional
|
||||||
|
logic from our inductive hypotheses concerning the subformulas of psi.
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( The final case is when the principal connective of psi is a
|
||||||
|
quantifier. This case is handled using the following axiom: $)
|
||||||
|
|
||||||
|
${ $d x y $.
|
||||||
|
$d y t $.
|
||||||
|
all_elim_hyp2 $e |- implies = x t
|
||||||
|
iff phi chi $.
|
||||||
|
all_elim2 $a |- implies = x t
|
||||||
|
iff quant y phi
|
||||||
|
quant y chi $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( The proof of Proposition 3.1 is now complete. We apply it to phi
|
||||||
|
and get that Metamath proves:
|
||||||
|
|- implies = x t
|
||||||
|
iff phi phi[t/x]
|
||||||
|
|
||||||
|
Here phi and t stand for the particular wff and term of t under
|
||||||
|
discussion and are not literal metavariables of Metamath.
|
||||||
|
|
||||||
|
We also know at this point that Metamath proves:
|
||||||
|
|
||||||
|
|- implies forall x phi
|
||||||
|
forall x implies = x t
|
||||||
|
phi
|
||||||
|
|
||||||
|
We would be done if we could prove in Metamath:
|
||||||
|
|
||||||
|
|- implies forall x implies = x t
|
||||||
|
phi
|
||||||
|
phi[t/x]
|
||||||
|
|
||||||
|
But this will follow easily from the next axiom [which is inelegant
|
||||||
|
but correct].
|
||||||
|
|
||||||
|
$)
|
||||||
|
|
||||||
|
${
|
||||||
|
$d x chi $.
|
||||||
|
$d x t $.
|
||||||
|
|
||||||
|
all_elim3_hyp1 $e |- implies = x t
|
||||||
|
iff phi chi $.
|
||||||
|
all_elim3 $a |- implies forall x implies = x t
|
||||||
|
phi
|
||||||
|
chi $. $}
|
||||||
|
|
||||||
|
$( This completes our discussion of "forall-elimination". $)
|
||||||
|
$( It is time to introduce the definition of the
|
||||||
|
"exists" quantifier $)
|
||||||
|
|
||||||
|
exists_def $a |- iff
|
||||||
|
exists x phi
|
||||||
|
not forall x not phi $.
|
||||||
|
|
||||||
|
$( Of course, the axiom and rule of inference for "exists" follow from
|
||||||
|
this definition and the corresponding inference rule or axiom scheme
|
||||||
|
for "forall". $)
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
The non-logical axioms of Peano Arithmetic
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( At this point, we know that Metamath can prove any logically valid
|
||||||
|
wff of PA. It remains to add the axioms of PA. $)
|
||||||
|
|
||||||
|
$( First we give the particular axioms of PA. Then we discuss the
|
||||||
|
induction scheme $)
|
||||||
|
|
||||||
|
pa_ax1 $a |- not = 0 S x $.
|
||||||
|
pa_ax2 $a |- implies = S x S y
|
||||||
|
= x y $.
|
||||||
|
pa_ax3 $a |- = x
|
||||||
|
+ x 0 $.
|
||||||
|
pa_ax4 $a |- = S + x y
|
||||||
|
+ x S y $.
|
||||||
|
pa_ax5 $a |- = 0
|
||||||
|
* x 0 $.
|
||||||
|
pa_ax6 $a |- = + * x y x
|
||||||
|
* x S y $.
|
||||||
|
${
|
||||||
|
$d z x $. $d z y $.
|
||||||
|
pa_ax7 $a |- iff
|
||||||
|
< x y
|
||||||
|
exists z = y + x S z $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$( It suffices to give the induction axiom for the case when phi does
|
||||||
|
not contain x free. For the usual form of the axiom follows from this
|
||||||
|
special case by first order logic. $)
|
||||||
|
|
||||||
|
${
|
||||||
|
$d phi x $.
|
||||||
|
$d x y $.
|
||||||
|
induction $a
|
||||||
|
|- implies
|
||||||
|
and forall y implies = y 0 phi
|
||||||
|
forall x implies forall y implies = y x phi
|
||||||
|
forall y implies = y S x phi
|
||||||
|
forall x forall y implies = y x phi $.
|
||||||
|
$}
|
||||||
|
|
||||||
|
$(
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
Discussion of correctness
|
||||||
|
#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
|
||||||
|
$)
|
||||||
|
|
||||||
|
$(
|
||||||
|
Let's agree that when I say "Metamath proves PHI" I mean "Metamath"
|
||||||
|
enriched with all the preceding axioms in this document.
|
||||||
|
|
||||||
|
The issue is the following. For what formulas Phi is there a proof in
|
||||||
|
Metamath from no $e type assumptions of the sequencce
|
||||||
|
|- Phi.
|
||||||
|
|
||||||
|
(Recall that I am identifying the well-formed formulas of Peano with
|
||||||
|
certain of the Metamath strings of symbols. This is done by
|
||||||
|
identifying the object variables of our language with the
|
||||||
|
metavariables of type var.)
|
||||||
|
|
||||||
|
The claim is that these are precisely those Phi which are theorems of
|
||||||
|
the usual formulation of Peano Arithmetic.
|
||||||
|
|
||||||
|
One direction should be clear by this point. We have developed the
|
||||||
|
first order predicate calculus within Metamath and included the usual
|
||||||
|
axioms of Peano arithmetic [or equivalents]. So any theorem of Peano
|
||||||
|
Arithmetic [as usually formulated] can be proved in Metamath.
|
||||||
|
|
||||||
|
To go in the other direction, suppose that there is a proof in
|
||||||
|
Metamath of |- Phi. So the final line of the proof contains only
|
||||||
|
variables of type var. But there might well be variables of other
|
||||||
|
kinds in the body of the proof. For example, there might be a variable
|
||||||
|
phi of kind wff.
|
||||||
|
|
||||||
|
The critical such variables are those that appear in lines of the
|
||||||
|
proof beginning with |-. What we do is replace such variables (of
|
||||||
|
kind different than var) [one by one] by sequences of constants of the
|
||||||
|
same type. (So phi might be replaced by the three symbol string "= 0
|
||||||
|
0".) It is not hard to see that after this substitution the result can
|
||||||
|
be massaged to a correct proof. There are two points to notice.
|
||||||
|
|
||||||
|
a) Since the string by which we replaced the variable contains no
|
||||||
|
variables itself the process converges and no disjointness
|
||||||
|
conditions [$d restrictions] are violated.
|
||||||
|
|
||||||
|
b) We may have to add a trivial few lines to prove the "type
|
||||||
|
assertion". In our example, the line "wff phi" will be replaced
|
||||||
|
by the line "wff = 0 0". This line is no longer immediate but
|
||||||
|
must be proved by a four line argument.
|
||||||
|
|
||||||
|
At the end, there results a proof where all the lines that begin with
|
||||||
|
"|-" contain only variables of type var. But now our correctness
|
||||||
|
assumptions allow us to verify step by step that each such line is a
|
||||||
|
theorem of Peano arithmetic.
|
||||||
|
$)
|
||||||
|
|
||||||
|
$( For Emacs $)
|
||||||
|
$( Local Variables: $)
|
||||||
|
$( eval:'(show-paren-mode t) $)
|
||||||
|
$( End: $)
|
Loading…
Reference in New Issue
Block a user