summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJose Antonio Ortega Ruiz <jao@gnu.org>2001-03-22 03:01:01 +0000
committerJose Antonio Ortega Ruiz <jao@gnu.org>2001-03-22 03:01:01 +0000
commit1c345e559710ec6200f7d508629bd24457a20a80 (patch)
tree4ebccd7c4719cf56da7151af6659992bd1dbb276
parent50375f34b611281a3b05a37221e2baa143f5f5ca (diff)
downloadmdk-1c345e559710ec6200f7d508629bd24457a20a80.tar.gz
mdk-1c345e559710ec6200f7d508629bd24457a20a80.tar.bz2
initial import (sf 0.3beta)
-rw-r--r--.cvsignore18
-rw-r--r--AUTHORS6
-rw-r--r--COPYING339
-rw-r--r--ChangeLog0
-rw-r--r--INSTALL309
-rw-r--r--Makefile.am20
-rw-r--r--NEWS69
-rw-r--r--README44
-rw-r--r--THANKS22
-rw-r--r--TODO9
-rw-r--r--acconfig.h10
-rw-r--r--aclocal.m41082
-rwxr-xr-xautogen.sh91
-rw-r--r--configure.in118
-rw-r--r--doc/.cvsignore12
-rw-r--r--doc/Makefile.am28
-rw-r--r--doc/gpl.texi400
-rw-r--r--doc/mdk.texi213
-rw-r--r--doc/mdk_bugs.texi16
-rw-r--r--doc/mdk_emixvm.texi25
-rw-r--r--doc/mdk_gmixvm.texi118
-rw-r--r--doc/mdk_gstart.texi433
-rw-r--r--doc/mdk_index.texi10
-rw-r--r--doc/mdk_install.texi180
-rw-r--r--doc/mdk_intro.texi48
-rw-r--r--doc/mdk_mixasm.texi79
-rw-r--r--doc/mdk_mixvm.texi478
-rw-r--r--doc/mdk_tut.texi1259
-rw-r--r--doc/ss_devices.pngbin0 -> 16621 bytes
-rw-r--r--doc/ss_mix.pngbin0 -> 12642 bytes
-rw-r--r--doc/ss_mix.txt31
-rw-r--r--doc/ss_mixal.pngbin0 -> 14536 bytes
-rw-r--r--doc/ss_worddlg.pngbin0 -> 15050 bytes
-rw-r--r--misc/.cvsignore2
-rw-r--r--misc/Makefile.am14
-rw-r--r--misc/mixvm.el157
-rw-r--r--mixgtk/.cvsignore7
-rw-r--r--mixgtk/Makefile.am31
-rw-r--r--mixgtk/mixgtk.c91
-rw-r--r--mixgtk/mixgtk.glade1703
-rw-r--r--mixgtk/mixgtk_cmd_dispatcher.c314
-rw-r--r--mixgtk/mixgtk_cmd_dispatcher.h55
-rw-r--r--mixgtk/mixgtk_device.c155
-rw-r--r--mixgtk/mixgtk_device.h42
-rw-r--r--mixgtk/mixgtk_gen_handlers.c95
-rw-r--r--mixgtk/mixgtk_gen_handlers.h46
-rw-r--r--mixgtk/mixgtk_input.c189
-rw-r--r--mixgtk/mixgtk_input.h49
-rw-r--r--mixgtk/mixgtk_mixal.c213
-rw-r--r--mixgtk/mixgtk_mixal.h60
-rw-r--r--mixgtk/mixgtk_mixvm.c423
-rw-r--r--mixgtk/mixgtk_mixvm.h84
-rw-r--r--mixgtk/mixgtk_widgets.c112
-rw-r--r--mixgtk/mixgtk_widgets.h80
-rw-r--r--mixlib/.cvsignore7
-rw-r--r--mixlib/Makefile.am33
-rw-r--r--mixlib/mix.c63
-rw-r--r--mixlib/mix.h65
-rw-r--r--mixlib/mix_code_file.c326
-rw-r--r--mixlib/mix_code_file.h106
-rw-r--r--mixlib/mix_device.c163
-rw-r--r--mixlib/mix_device.h151
-rw-r--r--mixlib/mix_eval.c191
-rw-r--r--mixlib/mix_eval.h110
-rw-r--r--mixlib/mix_eval_scanner.l265
-rw-r--r--mixlib/mix_file.c140
-rw-r--r--mixlib/mix_file.h61
-rw-r--r--mixlib/mix_ins.c269
-rw-r--r--mixlib/mix_ins.h195
-rw-r--r--mixlib/mix_io.c219
-rw-r--r--mixlib/mix_io.h123
-rw-r--r--mixlib/mix_parser.c525
-rw-r--r--mixlib/mix_parser.h110
-rw-r--r--mixlib/mix_scanner.l532
-rw-r--r--mixlib/mix_src_file.c157
-rw-r--r--mixlib/mix_src_file.h57
-rw-r--r--mixlib/mix_symbol_table.c196
-rw-r--r--mixlib/mix_symbol_table.h109
-rw-r--r--mixlib/mix_types.c566
-rw-r--r--mixlib/mix_types.h291
-rw-r--r--mixlib/mix_vm.c562
-rw-r--r--mixlib/mix_vm.h204
-rw-r--r--mixlib/mix_vm_clock.c68
-rw-r--r--mixlib/mix_vm_clock.h55
-rw-r--r--mixlib/mix_vm_command.c1167
-rw-r--r--mixlib/mix_vm_command.h160
-rw-r--r--mixlib/mix_vm_dump.c147
-rw-r--r--mixlib/mix_vm_dump.h91
-rw-r--r--mixlib/testsuite/.cvsignore28
-rw-r--r--mixlib/testsuite/Makefile.am28
-rw-r--r--mixlib/testsuite/mix_device_t.c76
-rw-r--r--mixlib/testsuite/mix_eval_t.c119
-rw-r--r--mixlib/testsuite/mix_ins_t.c79
-rw-r--r--mixlib/testsuite/mix_parser_t.c85
-rw-r--r--mixlib/testsuite/mix_types_t.c361
-rw-r--r--mixlib/testsuite/mix_vm_ins_t.c500
-rw-r--r--mixlib/testsuite/test.h44
-rw-r--r--mixlib/xmix_device.c131
-rw-r--r--mixlib/xmix_device.h77
-rw-r--r--mixlib/xmix_eval.h55
-rw-r--r--mixlib/xmix_io.c57
-rw-r--r--mixlib/xmix_io.h64
-rw-r--r--mixlib/xmix_parser.h107
-rw-r--r--mixlib/xmix_vm.c567
-rw-r--r--mixlib/xmix_vm.h117
-rw-r--r--mixutils/.cvsignore6
-rw-r--r--mixutils/Makefile.am18
-rw-r--r--mixutils/mixasm.c126
-rw-r--r--mixutils/mixasm_comp.c72
-rw-r--r--mixutils/mixasm_comp.h35
-rw-r--r--mixutils/mixvm.c155
-rw-r--r--mixutils/mixvm_command.c367
-rw-r--r--mixutils/mixvm_command.h35
-rw-r--r--mixutils/mixvm_loop.c86
-rw-r--r--po/.cvsignore7
-rw-r--r--po/ChangeLog3
-rw-r--r--po/POTFILES.in10
-rw-r--r--samples/.cvsignore36
-rw-r--r--samples/Makefile.am14
-rw-r--r--samples/hello.mixal11
-rw-r--r--samples/primes.mixal54
-rw-r--r--samples/primes.result51
-rw-r--r--samples/stress1.mixal9
-rw-r--r--samples/stress2.mixal14
-rw-r--r--samples/stress4.mixal7
125 files changed, 20484 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..117e735
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,18 @@
+.emacs.desktop
+Makefile
+Makefile.in
+blah
+config.cache
+config.h
+config.h.in
+config.log
+config.status
+configure
+intl
+mdk-0.1.1.tar.gz
+mdk-0.1.tar.gz
+mdk-0.2.tar.gz
+stamp-h
+stamp-h.in
+test
+mixmvc
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..fadc4e2
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,6 @@
+Authors of GNU MDK.
+See also the files THANKS and ChangeLog.
+
+Jose A. Ortega Ruiz designed and implemented mdk.
+
+Philip E. King designed and implemented mixvm.el. \ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..0e5eb99
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,309 @@
+1. Installing MDK
+
+ 1.1 Download the source tarball
+ 1.2 Requirements
+ 1.3 Basic installation
+ 1.4 Emacs support
+ 1.5 Special configure flags
+ 1.6 Generic configure help
+
+1.1 Download the source tarball
+-------------------------------
+
+GNU MDK is distributed as a source tarball available for download in the
+following URLs:
+
+ * ftp://ftp.gnu.org/pub/gnu/mdk (or one of its mirrors)
+ * http://sourceforge.net/project/showfiles.php?group_id=13897
+
+The above sites contain the latest stable releases of MDK. The development
+branch is available at:
+
+ * http://sourceforge.net/cvs/?group_id=13897
+
+After you have downloaded the source tarball, unpack it in a directory of
+your choice using the command:
+
+ tar xfvz mdk-X.Y.tar.gz
+
+where X.Y stands for the downloaded version (the current stable release
+being version ).
+
+
+1.2 Requirements
+----------------
+
+In order to build and install MDK, you will need the following libraries
+installed in your system:
+
+ * GLIB 1.2.0 (required)
+ * GNU Flex 2.3 (required)
+ * GTK+ 1.2.0 (optional)
+ * libglade (optional)
+ * GNU readline and history libraries (optional)
+
+If present, readline and history are used to provide command completion and
+history management to the command line MIX virtual machine, mixvm GTK+ and
+libglade are needed if you want to build the graphical interface to the MIX
+virtual machine, gmixvm.
+
+Please note: you need both the libraries and the headers; this means both
+the library package and the `-dev' package if you do not compile your
+libraries yourself (ex: installing `libgtk1.2' and `libgtk1.2-dev' on
+Debian).
+
+
+1.3 Basic installation
+----------------------
+
+MDK uses GNU Autoconf and Automake tools, and, therefore, should be built
+and installed without hassle using the following commands inside the source
+directory:
+
+ ./configure
+ make
+ make install
+
+where the last one must be run as root.
+
+The first command, configure, will setup the makefiles for your system. In
+particular, configure will look for GTK+ and libglade, and, if they are
+present, will generate the appropiate makefiles for building the gmixvm
+graphical user interface. Upon completion, you should see a message with the
+configuration results like the following:
+
+ *** GNU MDK 0.3 has been successfully configured. ***
+
+ Type make to build the following utilities:
+ - mixasm (MIX assembler)
+ - mixvm (MIX virtual machine, with readline support)
+ - gmixvm (mixvm GTK+ GUI)
+
+where the last line may be missing if you lack the above mentioned
+libraries.
+
+The next command, make, will actually build the MDK programs in the
+following locations:
+
+ * `mixutils/mixasm'
+ * `mixutils/mixvm'
+ * `mixgtk/gmixvm'
+
+You can run these programs from within their directories, but I recommend
+you to install them in proper locations using make install from a root
+shell.
+
+1.4 Emacs support
+-----------------
+
+mixvm can be run within an Emacs GUD buffer using the elisp
+program misc/mixvm.el, kindly contributed by Philip King.
+
+mixvm.el provides an interface between mdk's mixvm
+and Emacs, via GUD. Place this file in your load-path,
+optionally adding the following line to your .emacs file:
+
+(autoload 'mixvm "mixvm" "mixvm/gud interaction" t)
+
+
+1.5 Special configure flags
+---------------------------
+
+You can fine tunning the configuration process using the following switches
+with configure:
+
+User Option: --enable-gui[=yes|no]
+User Option: --disable-gui
+ Enables/disables the built of the MIX virtual machine GUI (gmixvm). If
+ the required libraries are missing (see section 1.2 Requirements) the
+ configure script with automatically disable this feature.
+
+User Option: --with-readline[=yes|no]
+User Option: --without-readline
+ Enables/disables the GNU Readline support for mixvm. If the required
+ libraries are missing (see section 1.2 Requirements) the configure
+ script with automatically disable this feature.
+
+
+1.6 Generic configure help
+--------------------------
+
+Basic Installation
+==================
+
+ For more information specific to this package, please read the README
+file. This source code distribution is autoconfiguring and you should be
+able to compile it and install it without manual interventions such as
+editing Makefiles, configuration files, and so on. These are generic
+instructions for people who are not familiar with installing autoconfiguring
+software.
+
+The simplest way to compile this package is to enter the source code
+main directory and do the following:
+
+ 1. Configure the source code by typing:
+ % sh ./configure
+
+ If you're planning to install the package into your home directory
+ or to a location other than `/usr/local' then add the flag
+ `--prefix=PATH' to `configure'. For example, if your home directory
+ is `/home/luser' you can configure the package to install itself there
+ by invoking:
+ % sh ./configure --prefix=/home/luser
+
+ While running, `configure' prints some messages telling which
+ features is it checking for.
+
+ 2. Compile the package by typing:
+ % make
+ Running `make' takes a while. If this is a very large package, now
+ is the time to go make some coffee.
+
+ 3. Some packages are bundled with self-tests for source-code
+ verification. If this package includes such tests, you can
+ optionally run them after compilation by typing
+ % make check
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. Type `make uninstall' to undo the installation.
+ During installation, the following files go to the following directories:
+ Executables -> /prefix/bin
+ Libraries -> /prefix/lib
+ Public header files -> /prefix/include
+ Man pages -> /prefix/man/man?
+ Info files -> /prefix/info
+ where `prefix' is either `/usr/local' or the PATH that you specified
+ in the `--prefix' flag.
+
+ If any of these directories do not presently exist, they will be
+ created on demand.
+
+ If you are installing in your home directory make sure that
+ `/home/luser/bin' is in your path. If you're using the bash shell
+ add this line at the end of your .cshrc file:
+ PATH="/home/luser/bin:${PATH}"
+ export PATH
+ If you are using csh or tcsh, then use this line instead:
+ setenv PATH /home/luser/bin:${PATH}
+ By prepending your home directory to the rest of the PATH you can
+ override systemwide installed software with your own custom installation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'.
+
+Compiler configuration
+======================
+
+ The `configure' shell script is responsible for choosing and configuring
+the compiler(s).
+
+The following options allow you to specify whether you
+want to enable or disable various debugging mechanisms:
+
+`--with-warnings'
+ Make the compilers very picky about warnings. Try this whenever you
+ write new code since it may catch a few bugs. This is not active by
+ default because all too often warnings can be too picky and scare
+ the end-user.
+
+`--disable-assert'
+ Compile without using assertions. This results in faster code,
+ but should not be used during developerment, or to run `make check'
+ which depends on assertions. It should only be used for production
+ runs on code that you believe is bug free.
+
+All programs are compiled with optimization level 2 by default (-O2).
+Occasionally that confuses the debugger when code is inlined. To disable
+optimization and enable debugging, set the shell environment variables
+CFLAGS, CXXFLAGS, FFLAGS to `-g'. On the bash shell, you can do this
+like this:
+ $ export CFLAGS="-g"
+ $ export CXXFLAGS="-g"
+ $ export FFLAGS="-g"
+On the tcsh shell, use the `setenv' command instead:
+ % setenv CFLAGS "-g"
+ ...etc...
+For other shell, please consult your shell's documentation.
+
+Similarly, you can increase the optimization level by assigning these
+variables to "-g -O3".
+
+The following options allow you to reconsider the `configure' shell script's
+choice of Fortran compilers.
+
+`--with-f2c'
+ Compile the Fortran code by translating it to C, even if a native
+ Fortran compiler is available. A copy of the f2c translator should be
+ bundled in the distribution. It will be compiled and then used to
+ compile your Fortran code.
+`--with-g77'
+ Compile the Fortran code with g77 even if a proprietary Fortran
+ compiler is available
+`--with-f77=F77'
+ Compile the Fortran code with the specified Fortran compiler.
+
+Depending on what languages the package uses, some of these options may
+or may not be available. To see what is available, type:
+ % sh ./configure --help
+
+About the configure script
+==========================
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+Advanced installation options.
+==============================
+
+ The `configure' script also understands the following more advanced
+options, to handle situations for which `--prefix' alone is not sufficient.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..d216294
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,20 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+EXTRA_DIST = ABOUT-NLS autogen.sh configure
+SUBDIRS = po intl doc mixlib mixutils mixgtk misc samples
+
+docdir = $(top_builddir)/doc
+
+html:
+ echo Making html in $(docdir)
+ cd $(docdir) && make html
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..b3ea3bb
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,69 @@
+GNU MDK -- History of visible changes.
+
+Copyright (C) 2000, 2001, Free Software Foundation, Inc.
+See the end for copying conditions.
+
+Please send mdk bug reports to jaortega@acm.org.
+
+*Version 0.2.1
+
+** MDK is now an official GNU packaga.
+
+*Version 0.2 (07/01/01)
+
+** mixvm provides virtual execution time statistics after each
+ invocation of run or next.
+
+** mixvm can trace instructions as they are executed. tron/troff
+ commands turn off/off instruction tracing.
+
+** mixvm accepts a new command, w2d, which computes the
+ decimal value of a MIX word given as a series of
+ bytes (e.g. - 01 00 34 32 22).
+
+** symbols can be defined at the mixvm prompt with the
+ new command ssym.
+
+** mixvm accepts a new command, weval, which allows the
+ evaluation of MIXAL w-expressions.
+
+** expressions containing strings of successive '*' are now
+ correctly evaluated.
+
+** When using block devices in mixvm, the buffers are now
+ flushed after each OUT operation.
+
+*Version 0.1.1 (18/11/00)
+
+** MDK is now compilable in rpm-based linuxes.
+** MDK fully compliant with Knuth's specification. In particular,
+ local symbols are now properly handled in special cases such as
+ 3H ORIG 3B
+ instructions. See samples/stress{1,2}.mixal.
+** Future references affected by unary minus are accepted
+ with a warning (they are banned in Knuth's specification).
+ Also future refs in EQU directives are now properly handled.
+ See samples/stress{3,4}.mixal.
+** When mixvm executes a program and reaches the end of the
+ available memory without encountering a HALT instruction,
+ it halts anyway.
+
+*Version 0.1 (31/10/00)
+
+** Initial version
+
+-------------------------------------------------------
+Copying information:
+
+Copyright (C) 2000, Free Software Foundation, Inc.
+
+ Permission is granted to anyone to make or distribute verbatim copies
+ of this document as received, in any medium, provided that the
+ copyright notice and this permission notice are preserved,
+ thus giving the recipient permission to redistribute in turn.
+
+ Permission is granted to distribute modified versions
+ of this document, or of portions of it,
+ under the above conditions, provided also that they
+ carry prominent notices stating who last changed them.
+
diff --git a/README b/README
new file mode 100644
index 0000000..af4447e
--- /dev/null
+++ b/README
@@ -0,0 +1,44 @@
+Welcome to GNU MDK.
+
+GNU MDK is an official GNU package [0].
+
+MDK stands for MIX Development Kit, and provides tools for developing
+and executing, in a MIX virtual machine, MIXAL programs.
+
+The MIX is Donald Knuth's mythical computer, described in the first
+volume of The Art of Computer Programming, which is programmed using
+MIXAL, the MIX assembly language.
+
+MDK includes a MIXAL assembler (mixasm) and a MIX virtual machine
+(mixvm) with a command line interface. In addition, a GTK+ GUI to
+mixvm, called gmixvm, is provided; and, in case you are an Emacs guy,
+you can try misc/mixvm.el, which allows running mixvm inside an Emacs
+GUD buffer.
+
+Using these interfaces, you can debug your MIXAL programs at source
+code level, and read/modify the contents of all the components of the
+MIX computer (including block devices, which are simultated using the
+file system).
+
+
+URLs:
+
+Project homepage: http://mdk.sourceforge.net
+Download: http://download.sourceforge.net/mdk/
+
+GNU MDK is free software. Please see the file COPYING for details.
+
+For documentation, please see the files in the doc subdirectory.
+
+For building and installation instructions please see the INSTALL file.
+
+For sample MIXAL programs, please see the samples subdirectory.
+
+For translations (MDK uses GNU's gettext), please see the po subdirectory[1].
+
+--
+[0] To learn more about GNU, the FSF and its goals, please visit
+ http://www.gnu.org.
+
+[1] New translations are welcome. If you'd like to contribute one,
+ please contact the author, jao@gnu.org.
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..0b46932
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,22 @@
+GNU MDK THANKS file
+
+GNU MDK is an official GNU package.
+It has originally been written by jose antonio ortega ruiz.
+Many people have further contributed to MDK by reporting problems,
+suggesting various improvements, or submitting actual code. Here is
+a list of these people. Help me keep it complete and exempt of errors.
+
+* Richard Stallman <rms@gnu.org> kindly suggested various improvements
+ to the documentation.
+
+* Philip Ellis King <pking@pdq.net> kindly provided MIXAL test programs
+ pinpointing bugs in the first MDK release, and useful discussions as well.
+
+* Agustin Navarro <anp@cantv.net> kindly tested the installation on
+ Mandrake and discovered a bug in the configuration process.
+
+* Vasilij <vasimba@mail.ru> kindly pointed out a bug in JRED.
+
+* MDK was inspired by Darius Bacon's MIXAL program <djello@well.sf.ca.us>
+ which can be installed in Debian 2.3 as the package "mixal".
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..ecbd427
--- /dev/null
+++ b/TODO
@@ -0,0 +1,9 @@
+- allow MIXAL instructions as commands at the mixvm prompt
+ (e.g. MIX > exec LDA 2000)
+- improve detection of pseudoinstructions in mixasm listing files
+
+* allow abbrevs of mixvm commands (e.g. ed file -> edit file)
+* ncurses based frontend
+* add GTK/GNOME support (see gaby's config hacks for making it optional)
+
+
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..06f5f49
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,10 @@
+#undef PACKAGE
+#undef VERSION
+#undef HAVE_LIBSM
+#undef HAVE_CATGETS
+#undef HAVE_GETTEXT
+#undef HAVE_LC_MESSAGES
+#undef HAVE_STPCPY
+#undef ENABLE_NLS
+#undef LOCALEDIR
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..240d7b7
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1082 @@
+dnl aclocal.m4 generated automatically by aclocal 1.4
+
+dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN(AM_CONFIG_HEADER,
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
+# Do all the work for Automake. This macro actually does too much --
+# some checks are only needed if your package does certain things.
+# But this isn't really a big deal.
+
+# serial 1
+
+dnl Usage:
+dnl AM_INIT_AUTOMAKE(package,version, [no-define])
+
+AC_DEFUN(AM_INIT_AUTOMAKE,
+[AC_REQUIRE([AC_PROG_INSTALL])
+PACKAGE=[$1]
+AC_SUBST(PACKAGE)
+VERSION=[$2]
+AC_SUBST(VERSION)
+dnl test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+ifelse([$3],,
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
+AC_REQUIRE([AM_SANITY_CHECK])
+AC_REQUIRE([AC_ARG_PROGRAM])
+dnl FIXME This is truly gross.
+missing_dir=`cd $ac_aux_dir && pwd`
+AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
+AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
+AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
+AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
+AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
+AC_REQUIRE([AC_PROG_MAKE_SET])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+AC_DEFUN(AM_SANITY_CHECK,
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftestfile
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
+ if test "[$]*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftestfile`
+ fi
+ if test "[$]*" != "X $srcdir/configure conftestfile" \
+ && test "[$]*" != "X conftestfile $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "[$]2" = conftestfile
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+rm -f conftest*
+AC_MSG_RESULT(yes)])
+
+dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
+dnl The program must properly implement --version.
+AC_DEFUN(AM_MISSING_PROG,
+[AC_MSG_CHECKING(for working $2)
+# Run test in a subshell; some versions of sh will print an error if
+# an executable is not found, even if stderr is redirected.
+# Redirect stdin to placate older versions of autoconf. Sigh.
+if ($2 --version) < /dev/null > /dev/null 2>&1; then
+ $1=$2
+ AC_MSG_RESULT(found)
+else
+ $1="$3/missing $2"
+ AC_MSG_RESULT(missing)
+fi
+AC_SUBST($1)])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# serial 1
+
+AC_DEFUN(AM_MAINTAINER_MODE,
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[ --enable-maintainer-mode enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer],
+ USE_MAINTAINER_MODE=$enableval,
+ USE_MAINTAINER_MODE=no)
+ AC_MSG_RESULT($USE_MAINTAINER_MODE)
+ AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes)
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST(MAINT)dnl
+]
+)
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi])
+
+
+# serial 1
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so. This macro tries various
+# options that select ANSI C on some system or another. It considers the
+# compiler to be in ANSI C mode if it handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(AM_PROG_CC_STDC,
+[AC_REQUIRE([AC_PROG_CC])
+AC_BEFORE([$0], [AC_C_INLINE])
+AC_BEFORE([$0], [AC_C_CONST])
+dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
+dnl a magic option to avoid problems with ANSI preprocessor commands
+dnl like #elif.
+dnl FIXME: can't do this because then AC_AIX won't work due to a
+dnl circular dependency.
+dnl AC_BEFORE([$0], [AC_PROG_CPP])
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(am_cv_prog_cc_stdc,
+[am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ AC_TRY_COMPILE(
+[#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+], [
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+],
+[am_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CC="$ac_save_CC"
+])
+if test -z "$am_cv_prog_cc_stdc"; then
+ AC_MSG_RESULT([none needed])
+else
+ AC_MSG_RESULT($am_cv_prog_cc_stdc)
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+])
+
+
+dnl AM_PROG_LEX
+dnl Look for flex, lex or missing, then run AC_PROG_LEX and AC_DECL_YYTEXT
+AC_DEFUN(AM_PROG_LEX,
+[missing_dir=ifelse([$1],,`cd $ac_aux_dir && pwd`,$1)
+AC_CHECK_PROGS(LEX, flex lex, "$missing_dir/missing flex")
+AC_PROG_LEX
+AC_DECL_YYTEXT])
+
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 5
+
+AC_DEFUN(AM_WITH_NLS,
+ [AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+
+ USE_INCLUDED_LIBINTL=no
+
+ dnl If we use NLS figure out what method
+ if test "$USE_NLS" = "yes"; then
+ AC_DEFINE(ENABLE_NLS)
+ AC_MSG_CHECKING([whether included gettext is requested])
+ AC_ARG_WITH(included-gettext,
+ [ --with-included-gettext use the GNU gettext library included here],
+ nls_cv_force_use_gnu_gettext=$withval,
+ nls_cv_force_use_gnu_gettext=no)
+ AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ dnl User does not insist on using GNU NLS library. Figure out what
+ dnl to use. If gettext or catgets are available (in this order) we
+ dnl use this. Else we have to fall back to GNU NLS library.
+ dnl catgets is only used if permitted by option --with-catgets.
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ AC_CHECK_HEADER(libintl.h,
+ [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+ [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+ gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ AC_CHECK_LIB(intl, bindtextdomain,
+ [AC_CACHE_CHECK([for gettext in libintl],
+ gt_cv_func_gettext_libintl,
+ [AC_CHECK_LIB(intl, gettext,
+ gt_cv_func_gettext_libintl=yes,
+ gt_cv_func_gettext_libintl=no)],
+ gt_cv_func_gettext_libintl=no)])
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ AC_DEFINE(HAVE_GETTEXT)
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+ if test "$MSGFMT" != "no"; then
+ AC_CHECK_FUNCS(dcgettext)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr],
+ [CATOBJEXT=.gmo
+ DATADIRNAME=share],
+ [CATOBJEXT=.mo
+ DATADIRNAME=lib])
+ INSTOBJEXT=.mo
+ fi
+ fi
+ ])
+
+ if test "$CATOBJEXT" = "NONE"; then
+ AC_MSG_CHECKING([whether catgets can be used])
+ AC_ARG_WITH(catgets,
+ [ --with-catgets use catgets functions if available],
+ nls_cv_use_catgets=$withval, nls_cv_use_catgets=no)
+ AC_MSG_RESULT($nls_cv_use_catgets)
+
+ if test "$nls_cv_use_catgets" = "yes"; then
+ dnl No gettext in C library. Try catgets next.
+ AC_CHECK_LIB(i, main)
+ AC_CHECK_FUNC(catgets,
+ [AC_DEFINE(HAVE_CATGETS)
+ INTLOBJS="\$(CATOBJS)"
+ AC_PATH_PROG(GENCAT, gencat, no)dnl
+ if test "$GENCAT" != "no"; then
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, no)
+ if test "$GMSGFMT" = "no"; then
+ AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)
+ fi
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.cat
+ INSTOBJEXT=.cat
+ DATADIRNAME=lib
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi])
+ fi
+ fi
+
+ if test "$CATOBJEXT" = "NONE"; then
+ dnl Neither gettext nor catgets in included in the C library.
+ dnl Fall back on GNU gettext library.
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions used to generate GNU NLS library.
+ INTLOBJS="\$(GETTOBJS)"
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_SUBST(MSGFMT)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+
+ dnl Test whether we really found GNU xgettext.
+ if test "$XGETTEXT" != ":"; then
+ dnl If it is no GNU xgettext we define it as : so that the
+ dnl Makefiles still can work.
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ AC_MSG_RESULT(
+ [found xgettext program is not GNU xgettext; ignore it])
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+ AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl)
+ AC_OUTPUT_COMMANDS(
+ [case "$CONFIG_FILES" in *po/Makefile.in*)
+ sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+ esac])
+
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ dnl These rules are solely for the distribution goal. While doing this
+ dnl we only have to keep exactly one list of the available catalogs
+ dnl in configure.in.
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+ dnl Make all variables we use known to autoconf.
+ AC_SUBST(USE_INCLUDED_LIBINTL)
+ AC_SUBST(CATALOGS)
+ AC_SUBST(CATOBJEXT)
+ AC_SUBST(DATADIRNAME)
+ AC_SUBST(GMOFILES)
+ AC_SUBST(INSTOBJEXT)
+ AC_SUBST(INTLDEPS)
+ AC_SUBST(INTLLIBS)
+ AC_SUBST(INTLOBJS)
+ AC_SUBST(POFILES)
+ AC_SUBST(POSUB)
+ ])
+
+AC_DEFUN(AM_GNU_GETTEXT,
+ [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_RANLIB])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+ AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([AC_C_INLINE])dnl
+ AC_REQUIRE([AC_TYPE_OFF_T])dnl
+ AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+ AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+ AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h sys/param.h])
+ AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+strdup __argz_count __argz_stringify __argz_next])
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ AC_CHECK_FUNCS(stpcpy)
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ AC_DEFINE(HAVE_STPCPY)
+ fi
+
+ AM_LC_MESSAGES
+ AM_WITH_NLS
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ AC_MSG_CHECKING(for catalogs to be installed)
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ AC_MSG_RESULT($LINGUAS)
+ fi
+
+ dnl Construct list of names of catalog files to be constructed.
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ dnl The reference to <locale.h> in the installed <libintl.h> file
+ dnl must be resolved because we cannot expect the users of this
+ dnl to define HAVE_LOCALE_H.
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+ AC_SUBST(INCLUDE_LOCALE_H)
+
+ dnl Determine which catalog format we have (if any is needed)
+ dnl For now we know about two different formats:
+ dnl Linux libc-5 and the normal X/Open format
+ test -d intl || mkdir intl
+ if test "$CATOBJEXT" = ".cat"; then
+ AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+ dnl Transform the SED scripts while copying because some dumb SEDs
+ dnl cannot handle comments.
+ sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
+ fi
+ dnl po2tbl.sed is always needed.
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
+
+ dnl In the intl/Makefile.in we have a special dependency which makes
+ dnl only sense for gettext. We comment this out for non-gettext
+ dnl packages.
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+ AC_SUBST(GT_NO)
+ AC_SUBST(GT_YES)
+
+ dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+ dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
+ dnl Try to locate is.
+ MKINSTALLDIRS=
+ if test -n "$ac_aux_dir"; then
+ MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+ fi
+ if test -z "$MKINSTALLDIRS"; then
+ MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+ fi
+ AC_SUBST(MKINSTALLDIRS)
+
+ dnl *** For now the libtool support in intl/Makefile is not for real.
+ l=
+ AC_SUBST(l)
+
+ dnl Generate list of files to be processed by xgettext which will
+ dnl be included in po/Makefile.
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ ])
+
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ /*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file can be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+ [if test $ac_cv_header_locale_h = yes; then
+ AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+ [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+ am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ AC_DEFINE(HAVE_LC_MESSAGES)
+ fi
+ fi])
+
+# Configure paths for GLIB
+# Owen Taylor 97-11-3
+
+dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or
+dnl gthread is specified in MODULES, pass to glib-config
+dnl
+AC_DEFUN(AM_PATH_GLIB,
+[dnl
+dnl Get the cflags and libraries from the glib-config script
+dnl
+AC_ARG_WITH(glib-prefix,[ --with-glib-prefix=PFX Prefix where GLIB is installed (optional)],
+ glib_config_prefix="$withval", glib_config_prefix="")
+AC_ARG_WITH(glib-exec-prefix,[ --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)],
+ glib_config_exec_prefix="$withval", glib_config_exec_prefix="")
+AC_ARG_ENABLE(glibtest, [ --disable-glibtest Do not try to compile and run a test GLIB program],
+ , enable_glibtest=yes)
+
+ if test x$glib_config_exec_prefix != x ; then
+ glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config
+ fi
+ fi
+ if test x$glib_config_prefix != x ; then
+ glib_config_args="$glib_config_args --prefix=$glib_config_prefix"
+ if test x${GLIB_CONFIG+set} != xset ; then
+ GLIB_CONFIG=$glib_config_prefix/bin/glib-config
+ fi
+ fi
+
+ for module in . $4
+ do
+ case "$module" in
+ gmodule)
+ glib_config_args="$glib_config_args gmodule"
+ ;;
+ gthread)
+ glib_config_args="$glib_config_args gthread"
+ ;;
+ esac
+ done
+
+ AC_PATH_PROG(GLIB_CONFIG, glib-config, no)
+ min_glib_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
+ no_glib=""
+ if test "$GLIB_CONFIG" = "no" ; then
+ no_glib=yes
+ else
+ GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags`
+ GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs`
+ glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_glibtest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$GLIB_LIBS $LIBS"
+dnl
+dnl Now check if the installed GLIB is sufficiently new. (Also sanity
+dnl checks the results of glib-config to some extent
+dnl
+ rm -f conf.glibtest
+ AC_TRY_RUN([
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.glibtest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_glib_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_glib_version");
+ exit(1);
+ }
+
+ if ((glib_major_version != $glib_config_major_version) ||
+ (glib_minor_version != $glib_config_minor_version) ||
+ (glib_micro_version != $glib_config_micro_version))
+ {
+ printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
+ $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf ("*** was found! If glib-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n");
+ printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+ else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+ (glib_minor_version != GLIB_MINOR_VERSION) ||
+ (glib_micro_version != GLIB_MICRO_VERSION))
+ {
+ printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+ GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ }
+ else
+ {
+ if ((glib_major_version > major) ||
+ ((glib_major_version == major) && (glib_minor_version > minor)) ||
+ ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n",
+ glib_major_version, glib_minor_version, glib_micro_version);
+ printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the glib-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n");
+ printf("*** correct copy of glib-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_glib" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$GLIB_CONFIG" = "no" ; then
+ echo "*** The glib-config script installed by GLIB could not be found"
+ echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GLIB_CONFIG environment variable to the"
+ echo "*** full path to glib-config."
+ else
+ if test -f conf.glibtest ; then
+ :
+ else
+ echo "*** Could not run GLIB test program, checking why..."
+ CFLAGS="$CFLAGS $GLIB_CFLAGS"
+ LIBS="$LIBS $GLIB_LIBS"
+ AC_TRY_LINK([
+#include <glib.h>
+#include <stdio.h>
+], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+ echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GLIB was incorrectly installed"
+ echo "*** or that you have moved GLIB since it was installed. In the latter case, you"
+ echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GLIB_CFLAGS=""
+ GLIB_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+ rm -f conf.glibtest
+])
+
+# Configure paths for GTK+
+# Owen Taylor 97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)],
+ gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+ gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program],
+ , enable_gtktest=yes)
+
+ for module in . $4
+ do
+ case "$module" in
+ gthread)
+ gtk_config_args="$gtk_config_args gthread"
+ ;;
+ esac
+ done
+
+ if test x$gtk_config_exec_prefix != x ; then
+ gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+ fi
+ fi
+ if test x$gtk_config_prefix != x ; then
+ gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+ if test x${GTK_CONFIG+set} != xset ; then
+ GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+ fi
+ fi
+
+ AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+ min_gtk_version=ifelse([$1], ,0.99.7,$1)
+ AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+ no_gtk=""
+ if test "$GTK_CONFIG" = "no" ; then
+ no_gtk=yes
+ else
+ GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+ GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+ gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "x$enable_gtktest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$GTK_LIBS $LIBS"
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+ rm -f conf.gtktest
+ AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+ int major, minor, micro;
+ char *tmp_version;
+
+ system ("touch conf.gtktest");
+
+ /* HP/UX 9 (%@#!) writes to sscanf strings */
+ tmp_version = g_strdup("$min_gtk_version");
+ if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+ if ((gtk_major_version != $gtk_config_major_version) ||
+ (gtk_minor_version != $gtk_config_minor_version) ||
+ (gtk_micro_version != $gtk_config_micro_version))
+ {
+ printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n",
+ $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf ("*** was found! If gtk-config was correct, then it is best\n");
+ printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+ printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+ printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+ printf("*** required on your system.\n");
+ printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+ printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+ printf("*** before re-running configure\n");
+ }
+#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION)
+ else if ((gtk_major_version != GTK_MAJOR_VERSION) ||
+ (gtk_minor_version != GTK_MINOR_VERSION) ||
+ (gtk_micro_version != GTK_MICRO_VERSION))
+ {
+ printf("*** GTK+ header files (version %d.%d.%d) do not match\n",
+ GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+ printf("*** library (version %d.%d.%d)\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ }
+#endif /* defined (GTK_MAJOR_VERSION) ... */
+ else
+ {
+ if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+ {
+ return 0;
+ }
+ else
+ {
+ printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+ gtk_major_version, gtk_minor_version, gtk_micro_version);
+ printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+ major, minor, micro);
+ printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+ printf("***\n");
+ printf("*** If you have already installed a sufficiently new version, this error\n");
+ printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+ printf("*** being found. The easiest way to fix this is to remove the old version\n");
+ printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+ printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+ printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+ printf("*** so that the correct libraries are found at run-time))\n");
+ }
+ }
+ return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ if test "x$no_gtk" = x ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ if test "$GTK_CONFIG" = "no" ; then
+ echo "*** The gtk-config script installed by GTK could not be found"
+ echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+ echo "*** your path, or set the GTK_CONFIG environment variable to the"
+ echo "*** full path to gtk-config."
+ else
+ if test -f conf.gtktest ; then
+ :
+ else
+ echo "*** Could not run GTK test program, checking why..."
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+ AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding GTK or finding the wrong"
+ echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+ echo "***"
+ echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+ echo "*** came with the system with the command"
+ echo "***"
+ echo "*** rpm --erase --nodeps gtk gtk-devel" ],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+ echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+ echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ fi
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+ AC_SUBST(GTK_CFLAGS)
+ AC_SUBST(GTK_LIBS)
+ rm -f conf.gtktest
+])
+
+# a macro to get the libs/cflags for libglade
+# serial 1
+
+dnl AM_PATH_LIBGLADE([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]])
+dnl Test to see if libglade is installed, and define LIBGLADE_CFLAGS, LIBS
+dnl
+AC_DEFUN(AM_PATH_LIBGLADE,
+[dnl
+dnl Get the cflags and libraries from the libglade-config script
+dnl
+AC_ARG_WITH(libglade-config,
+[ --with-libglade-config=LIBGLADE_CONFIG Location of libglade-config],
+LIBGLADE_CONFIG="$withval")
+
+module_args=
+for module in . $3; do
+ case "$module" in
+ gnome)
+ module_args="$module_args gnome"
+ ;;
+ bonobo)
+ module_args="$module_args bonobo"
+ ;;
+ gnomedb)
+ module_args="$module_args gnomedb"
+ ;;
+ esac
+done
+
+AC_PATH_PROG(LIBGLADE_CONFIG, libglade-config, no)
+AC_MSG_CHECKING(for libglade)
+if test "$LIBGLADE_CONFIG" = "no"; then
+ AC_MSG_RESULT(no)
+ ifelse([$2], , :, [$2])
+else
+ if $LIBGLADE_CONFIG --check $module_args; then
+ LIBGLADE_CFLAGS=`$LIBGLADE_CONFIG --cflags $module_args`
+ LIBGLADE_LIBS=`$LIBGLADE_CONFIG --libs $module_args`
+ AC_MSG_RESULT(yes)
+ ifelse([$1], , :, [$1])
+ else
+ echo "*** libglade was not compiled with support for $module_args" 1>&2
+ AC_MSG_RESULT(no)
+ ifelse([$2], , :, [$2])
+ fi
+fi
+AC_SUBST(LIBGLADE_CFLAGS)
+AC_SUBST(LIBGLADE_LIBS)
+])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..bda8fda
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+PROJECT=mdk
+TEST_TYPE=-d
+FILE=mixlib
+
+DIE=0
+
+grep "^AM_GNU_GETTEXT" $srcdir/configure.in >/dev/null && {
+ (gettext --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`gettext' installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake installed to compile $PROJECT."
+ echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ NO_AUTOMAKE=yes
+}
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: Missing \`aclocal'. The version of \`automake'"
+ echo "installed doesn't appear recent enough."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+}
+
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+if test -z "$*"; then
+ echo "I am going to run ./configure with no arguments - if you wish "
+ echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+case $CC in
+*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
+esac
+
+echo "Running gettextize... Ignore non-fatal messages."
+echo "no" | gettextize --force
+
+echo "Running aclocal ..."
+aclocal $ACLOCAL_FLAGS
+
+# optionally feature autoheader
+(autoheader --version) < /dev/null > /dev/null 2>&1 && autoheader
+
+echo "Running automake --add-missing --gnu $am_opt ..."
+automake -a --gnu $am_opt
+
+echo "Running autoconf ..."
+autoconf
+cd $ORIGDIR
+
+$srcdir/configure --enable-maintainer-mode "$@"
+
+echo
+echo "Now type 'make' to compile $PROJECT."
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..c27cde4
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,118 @@
+# Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+AC_INIT(mixlib/mix.h)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(mdk,0.3)
+
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+
+AM_PROG_LEX
+AC_PROG_RANLIB
+
+dnl i18n stuff
+ALL_LINGUAS=""
+AM_GNU_GETTEXT
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+
+AC_DEFINE_UNQUOTED(LOCALEDIR, "${prefix}/share/locale")
+
+dnl Check for readline and history
+AC_ARG_WITH(readline,
+[ --with-readline build mixvm with readline support],
+[case "${withval}" in
+ yes) readl=true ;;
+ no) readl=false ;;
+ *) AC_MSG_ERROR(bad value ${withval} for --with-readline) ;;
+esac], [readl=true])
+
+if test x$readl = xtrue; then
+ AC_CHECK_LIB(ncurses, initscr, ,
+ [AC_MSG_WARN(Cannot find ncurses lib) readl=false])
+fi
+
+if test x$readl = xtrue; then
+ AC_CHECK_LIB(readline, readline, ,
+ [AC_MSG_WARN(Cannot find GNU readline lib) readl=false])
+fi
+
+if test x$readl = xtrue; then
+AC_CHECK_LIB(history, add_history, ,
+ [AC_MSG_WARN(Cannot find GNU history lib) readl=false])
+fi
+
+dnl Check for glib
+AM_PATH_GLIB(1.2.0,
+ [LIBS="$LIBS $GLIB_LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS"],
+ AC_MSG_ERROR(Cannot find GLIB), "gmodule" )
+
+dnl Check if the gtk gui is required
+AC_ARG_ENABLE(gui,
+[ --enable-gui build the GTK+ GUI for mixvm (gmixvm)],
+[case "${enableval}" in
+ yes) gui=true ;;
+ no) gui=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gui) ;;
+esac],[gui=true])
+
+dnl Check for gtk+
+if test x$gui = xtrue; then
+ AM_PATH_GTK(1.2.0,
+ [LIBS="$LIBS $GTK_LIBS" CFLAGS="$CFLAGS $GTK_CFLAGS"],
+ [AC_MSG_WARN(Cannot find GTK+: the GUI shall not be built) gui=false],
+ "gmodule" )
+fi
+
+dnl Check for libglade
+if test x$gui = xtrue; then
+ AM_PATH_LIBGLADE([LIBS="$LIBS $LIBGLADE_LIBS"
+ CFLAGS="$CFLAGS $LIBGLADE_CFLAGS"],
+ [AC_MSG_WARN(Cannot find GTK+: the GUI shall not be built) gui=false])
+fi
+
+AM_CONDITIONAL(MAKE_GUI, test x$gui = xtrue)
+
+CFLAGS="$CFLAGS -Wall"
+AC_SUBST(CFLAGS)
+
+AC_OUTPUT(
+Makefile
+doc/Makefile
+doc/html/Makefile
+mixlib/Makefile
+mixlib/testsuite/Makefile
+mixutils/Makefile
+mixgtk/Makefile
+misc/Makefile
+intl/Makefile
+samples/Makefile
+po/Makefile.in
+)
+
+if test x$readl = xtrue; then
+ addinfo=", with readline support"
+fi
+
+echo
+echo "*** GNU MDK $VERSION has been successfully configured. ***"
+echo
+echo "Type make to build the following utilities:"
+echo " - mixasm (MIX assembler${addinfo})"
+echo " - mixvm (MIX virtual machine)"
+if test x$gui = xtrue; then
+echo " - gmixvm (mixvm GTK+ GUI)"
+fi
+echo
diff --git a/doc/.cvsignore b/doc/.cvsignore
new file mode 100644
index 0000000..cad9468
--- /dev/null
+++ b/doc/.cvsignore
@@ -0,0 +1,12 @@
+Makefile
+Makefile.in
+mdk-0.1
+mdk-doc-html-0.2.tar.gz
+mdk-doc.tar.gz
+mdk.html
+mdk.info
+mdk.info-1
+mdk.info-2
+mdk.info-3
+stamp-vti
+version.texi
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..42953a8
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,28 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2000 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+SUBDIRS = html
+SUFFIXES = .html
+
+
+info_TEXINFOS = mdk.texi
+mdk_TEXINFOS = gpl.texi mdk_intro.texi mdk_tut.texi mdk_gstart.texi \
+ mdk_mixvm.texi mdk_emixvm.texi mdk_mixasm.texi mdk_bugs.texi \
+ mdk_index.texi
+
+html_docs = mdk.html
+
+.texi.html:
+ $(MAKEINFO) --html $<
+
+.PHONY: html
+html: version.texi gpl.texi $(html_docs) \ No newline at end of file
diff --git a/doc/gpl.texi b/doc/gpl.texi
new file mode 100644
index 0000000..361504a
--- /dev/null
+++ b/doc/gpl.texi
@@ -0,0 +1,400 @@
+@node Copying, Problems, mixasm, Top
+@chapter Copying
+@lowersections
+
+@unnumbered GNU GENERAL PUBLIC LICENSE
+@center Version 2, June 1991
+
+@display
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec 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.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end ifinfo
+
+@enumerate
+@item
+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.
+
+@item
+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.
+
+@item
+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:
+
+@enumerate a
+@item
+You must cause the modified files to carry prominent notices
+stating that you changed the files and the date of any change.
+
+@item
+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.
+
+@item
+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.)
+@end enumerate
+
+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.
+
+@item
+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:
+
+@enumerate a
+@item
+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,
+
+@item
+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,
+
+@item
+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.)
+@end enumerate
+
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+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.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+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.
+
+@item
+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 enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+@page
+@unnumberedsec 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.
+
+@smallexample
+@var{one line to give the program's name and an idea of what it does.}
+Copyright (C) 19@var{yy} @var{name of author}
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+@end smallexample
+
+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:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{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.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than @samp{show w} and
+@samp{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:
+
+@smallexample
+@group
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written
+by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end group
+@end smallexample
+
+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.
+
+@raisesections
diff --git a/doc/mdk.texi b/doc/mdk.texi
new file mode 100644
index 0000000..ba5b94f
--- /dev/null
+++ b/doc/mdk.texi
@@ -0,0 +1,213 @@
+\input texinfo
+@c %**start of header
+@setfilename mdk.info
+@settitle GNU MIX Development Kit (mdk)
+@finalout
+@setchapternewpage odd
+@c %**end of header
+
+@set UPDATED 20 February 2001
+@set EDITION 0.3
+@set VERSION 0.3
+@set JAO Jos@'e Antonio Ortega Ruiz
+@set PHILIP Philip E. King
+@footnotestyle separate
+
+@ifinfo
+This file documents the the GNU @sc{mdk} utilities for developing
+programs using Donald Knuth's MIX language.
+
+Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Copying'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end ifinfo
+
+@titlepage
+@title GNU MDK
+@subtitle GNU MIX Development Kit
+@subtitle Edition @value{EDITION}, for GNU @sc{mdk} Version @value{VERSION}
+@subtitle @value{UPDATED}
+@author by @value{JAO}
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 2000, 2001 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+sections entitled ``Copying'' and ``GNU General Public License'' are
+included exactly as in the original, and provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
+@end titlepage
+
+@node Top, Introduction, (dir), (dir)
+
+@ifinfo
+This file documents the GNU @sc{mdk} utilities to develop, run and debug
+programs written in the MIXAL programming language. MIXAL is an
+assembler-like language for programming a virtual computer called
+MIX. They were created by Donald Knuth in the first volume of @cite{The
+Art of Computer Programming} (Addison Wesley, 1997).
+
+GNU @sc{mdk} is an official GNU package.
+
+GNU @sc{mdk} was written by @value{JAO} and is released under the GNU
+General Public license (@pxref{Copying}), so that users are free to share
+and improve it.
+
+@value{PHILIP} has contributed to this package development with many
+helpful discussions, as well as actual code (@pxref{mixvm.el}).
+
+@end ifinfo
+
+@menu
+* Introduction::
+* Installing MDK::
+* MIX and MIXAL tutorial:: Learn the innards of MIX and MIXAL.
+* Getting started:: Basic usage of the @sc{mdk} tools.
+* mixvm.el:: Using @code{mixvm} within Emacs.
+* mixvm:: Invoking and using the MIX virtual machine.
+* gmixvm::
+* mixasm:: Invoking the MIXAL assembler.
+* Copying:: @sc{mdk} licensing terms.
+* Problems:: Reporting bugs.
+* Concept Index:: Index of concepts.
+
+
+
+
+
+
+
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Installing @sc{mdk}
+
+* Download::
+* Requirements::
+* Basic installation::
+* Emacs support::
+* Special configure flags::
+
+MIX and MIXAL tutorial
+
+* The MIX computer:: Architecture and instruction set
+ of the MIX computer.
+* MIXAL:: The MIX assembly language.
+
+The MIX computer
+
+* MIX architecture::
+* MIX instruction set::
+
+MIX instruction set
+
+* Instruction structure::
+* Loading operators::
+* Storing operators::
+* Arithmetic operators::
+* Address transfer operators::
+* Comparison operators::
+* Jump operators::
+* Input-output operators::
+* Conversion operators::
+* Shift operators::
+* Miscellaneous operators::
+* Execution times::
+
+MIXAL
+
+* Basic structure:: Writing basic MIXAL programs.
+* MIXAL directives:: Assembler directives.
+* Expressions:: Evaluation of expressions.
+* W-expressions:: Evaluation of w-expressions.
+* Local symbols:: Special symbol table entries.
+* Literal constants:: Specifying an immediate operand.
+
+Getting started
+
+* Writing a source file:: A sample MIXAL source file.
+* Compiling:: Using @code{mixasm} to compile source
+ files into binary format.
+* Running the program:: Running and debugging your program.
+
+Running the program
+
+* Non-interactive mode:: Running your programs non-interactively.
+* Interactive mode:: Running programs interactively.
+* Debugging:: Commands for debugging your programs.
+
+@code{mixvm}, the MIX computer simulator
+
+* Invocation:: Options when invoking @code{mixvm}.
+* Commands:: Commands available in interactive mode.
+* Devices:: MIX block devices implementation.
+
+Interactive commands
+
+* File commands:: Loading and executing programs.
+* Debug commands:: Debugging programs.
+* State commands:: Inspecting the virtual machine state.
+
+gmixvm
+
+* Invoking @code{gmixvm}::
+* MIX virtual machine::
+* Menu and status bars::
+
+@code{mixasm}, the MIXAL assembler
+
+* Invoking @code{mixasm}:: @code{mixasm} options
+
+@end detailmenu
+@end menu
+
+@include mdk_intro.texi
+@include mdk_install.texi
+@include mdk_tut.texi
+@include mdk_gstart.texi
+@include mdk_emixvm.texi
+@include mdk_mixvm.texi
+@include mdk_gmixvm.texi
+@include mdk_mixasm.texi
+@include gpl.texi
+@include mdk_bugs.texi
+@include mdk_index.texi
+
+
+@shortcontents
+@contents
+@bye
diff --git a/doc/mdk_bugs.texi b/doc/mdk_bugs.texi
new file mode 100644
index 0000000..7531daa
--- /dev/null
+++ b/doc/mdk_bugs.texi
@@ -0,0 +1,16 @@
+@node Problems, Concept Index, Copying, Top
+@chapter Reporting Bugs
+@cindex bugs
+@cindex problems
+@cindex questions
+@cindex suggestions
+
+If you have any questions, comments or suggestions, please send
+electronic mail to @email{jao@@gnu.org, the author}.
+
+If you find a bug in @sc{mdk}, please send electronic mail to
+@email{bug-mdk@@gnu.org, the @sc{mdk} bug list}.
+
+In your report, please include the version number, which you can find by
+running @w{@samp{mixasm --version}}. Also include in your message the
+output that the program produced and the output you expected.
diff --git a/doc/mdk_emixvm.texi b/doc/mdk_emixvm.texi
new file mode 100644
index 0000000..8fcbf55
--- /dev/null
+++ b/doc/mdk_emixvm.texi
@@ -0,0 +1,25 @@
+@node mixvm.el, mixvm, Getting started, Top
+@comment node-name, next, previous, up
+@chapter mixvm.el
+
+If you are an Emacs user and write your MIXAL programs using this
+editor, you will find the elisp program @file{mixvm.el} quite
+useful@footnote{@file{mixvm.el} has been kindly contributed by
+@value{PHILIP}. @file{mixvm.el} is based on a study of gdb, perldb, and
+pdb as found in @file{gud.el}, and @file{rubydb3x.el} distributed with
+the source code to the Ruby language.}. @file{mixvm.el} allows running
+the MIX virtual machine @code{mixvm} (@pxref{mixvm}) inside an Emacs
+@acronym{GUD} buffer, while visiting the MIXAL source file in another
+buffer.
+
+After installing @file{mixvm.el} (@pxref{Emacs support}), you can
+initiate an @sc{mdk}/@acronym{GUD} session inside Emacs with the command
+
+@example
+M-x mixvm
+@end example
+
+@noindent
+and you will have a @code{mixvm} prompt inside a newly created
+@acronym{GUD} buffer. @acronym{GUD} will reflect the current line in the
+corresponding source file buffer.
diff --git a/doc/mdk_gmixvm.texi b/doc/mdk_gmixvm.texi
new file mode 100644
index 0000000..f3ed33b
--- /dev/null
+++ b/doc/mdk_gmixvm.texi
@@ -0,0 +1,118 @@
+@node gmixvm, mixasm, mixvm, Top
+@comment node-name, next, previous, up
+@chapter gmixvm
+@cindex @code{gmixvm}
+@cindex GUI
+@cindex GTK+
+
+@menu
+* Invoking @code{gmixvm}:: Invoking the GTK+ interface.
+* MIX virtual machine:: The MIX virtual machine window.
+* Menu and status bars:: Available menu commands.
+@end menu
+
+@node Invoking @code{gmixvm}, MIX virtual machine, gmixvm, gmixvm
+@comment node-name, next, previous, up
+@section Invoking @code{gmixvm}
+
+If you have built @sc{mdk} with GTK+ support (@pxref{Installing MDK}), a
+graphical front-end for the MIX virtual machine will be available in
+your system. You can invoke it by typing
+
+@example
+gmixvm @kbd{RET}
+@end example
+
+@noindent
+at your command prompt. The @code{gmixvm} main window will appear,
+offering you a graphical interface to run and debug your MIX programs.
+
+@image{ss_mix}
+
+Apart from the menu and status bars, we can distinguish two zones (or
+halves) in this main window. In the upper half of @code{gmixvm}'s main
+window there is a notebook with three pages, namely,
+
+@itemize
+@item
+a MIX virtual machine view, which shows you the registers, flags, memory
+contents and time statistics of the virtual machine;
+@item
+a MIXAL source view, which shows the MIXAL file and lets you manage
+breakpoints;
+@item
+a Devices view, which shows you the output to character based MIX block
+devices.
+@end itemize
+
+@noindent
+On the other hand, the main window's lower half presents you a
+@code{mixvm} command prompt and a logging area where results of the
+issued commands are presented.
+
+The following sections describe the above mentioned components of
+@code{gmixvm}.
+
+@node MIX virtual machine, Menu and status bars, Invoking @code{gmixvm}, gmixvm
+@comment node-name, next, previous, up
+@section MIX virtual machine
+
+The first notebook's page displays the current status of the virtual
+machine. There you can find the registers' contents, the value of the
+comparison and overflow flags, the location pointer, a list with all MIX
+memory cells and their contents, and the time statistics (including
+total uptime, elapsed time since the last run command and total
+execution time for the currently loaded MIX program).
+
+Clicking any register entry, you will be prompted for a new register's
+contents
+@ifnotinfo
+(as shown in the next figure).
+@image{ss_worddlg}
+@end ifnotinfo
+
+In the same manner, click on any address of the memory cells list to be
+prompted for the new contents of the clicked cell. If you click the
+address column's title, a dialog asking you for a memory address will
+appear; if you introduce a valid address, this will be the first cell
+displayed in the scrollable list after you click the OK button.
+
+
+@node Menu and status bars, , MIX virtual machine, gmixvm
+@comment node-name, next, previous, up
+@section Menu and status bars
+
+The menu bar gives you access to the following commands:
+
+@deffn File Load...
+Opens a file dialog that lets you specify a binary MIX file to be loaded
+in the virtual machine's memory. It is equivalent to the @code{mixvm}'s
+@code{load} command (@pxref{File commands}).
+@end deffn
+
+@deffn File Exit
+Exits the application.
+@end deffn
+
+@deffn Debug Run
+Runs the currently loaded MIX program, up to the next breakpoint. It is
+equivalent to the @code{mixvm}'s @code{run} command (@pxref{Debug
+commands}).
+@end deffn
+
+@deffn Debug Next
+Executes the next MIX instruction. It is equivalent to the
+@code{mixvm}'s @code{next} command (@pxref{Debug commands}).
+@end deffn
+
+@deffn Debug Clear breakpoints
+Clears all currently set breakpoints. It is equivalent to the
+@code{mixvm}'s @code{cabp} command.
+@end deffn
+
+@deffn Help About...
+Shows information about @code{gmixvm}'s version and copyright.
+@end deffn
+
+On the other hand, the status bar displays the name of the last loaded
+MIX file.
diff --git a/doc/mdk_gstart.texi b/doc/mdk_gstart.texi
new file mode 100644
index 0000000..bde4160
--- /dev/null
+++ b/doc/mdk_gstart.texi
@@ -0,0 +1,433 @@
+@node Getting started, mixvm.el, MIX and MIXAL tutorial, Top
+@comment node-name, next, previous, up
+@chapter Getting started
+
+In this chapter, you will find a sample code-compile-run-debug session
+using the @sc{mdk} utilities. Familiarity with the MIX mythical computer
+and its assembly language MIXAL (as described in Knuth's TAOCP) is
+assumed; for a compact reminder, see @ref{MIX and MIXAL tutorial}.
+
+@menu
+* Writing a source file:: A sample MIXAL source file.
+* Compiling:: Using @code{mixasm} to compile source
+ files into binary format.
+* Running the program:: Running and debugging your program.
+@end menu
+
+@node Writing a source file, Compiling, Getting started, Getting started
+@comment node-name, next, previous, up
+@section Writing a source file
+@cindex MIXAL
+@cindex source file
+
+MIXAL programs can be written as ASCII files with your editor of choice.
+Here you have the mandatory @emph{hello world} as written in the MIXAL
+assembly language:
+
+@example
+* (1)
+* hello.mixal: say 'hello world' in MIXAL (2)
+* (3)
+* label ins operand comment (4)
+TERM EQU 19 the MIX console device number (5)
+ ORIG 1000 start address (6)
+START OUT MSG(TERM) output data at address MSG (7)
+ HLT halt execution (8)
+MSG ALF "MIXAL" (9)
+ ALF " HELL" (10)
+ ALF "O WOR" (11)
+ ALF "LD " (12)
+ END START end of the program (13)
+@end example
+
+@noindent MIXAL source files should have the extension @file{.mixal}
+when used with the @sc{mdk} utilities. As you can see in the above
+sample, each line in a MIXAL file can be divided into four fields
+separated by an arbitrary amount of whitespace characters (blanks and or
+tabs). While Knuth's definition of MIXAL each field must start at a
+fixed pre-defined column number, the @sc{mdk} assembler loosens this
+requirement and lets you format the file as you see fit. The only
+restrictions retained are for comment lines (like 1-4) which must begin
+with an asterisk (*) placed at column 1, and for the label field (see
+below) which, if present, must also start at column 1. The four fields
+in each non-comment line are:
+
+@itemize @minus
+@item
+an optional label, which either refers to the current memory address (as
+@code{START} and @code{MSG} in lines 7 and 9) or a defined symbol
+(@code{TERM}) (if present, the label must always start at the first
+column in its line, for the first whitespace in the line maks the
+beginning of the second field),
+@item
+an operation mnemonic, which can represent either a MIX instruction
+(@code{OUT} and @code{HLT} in lines 6 and 7 above), or an assembly
+pseudoinstruction.
+@item
+an optional operand for the (pseudo)instruction, and
+@item
+an optional free text comment.
+@end itemize
+
+@noindent Lines 9-12 of the @file{hello.mixal} file above also show the
+second (and last) difference between Knuth's MIXAL definition and ours:
+the operand of the @code{ALF} pseudoinstruction (a word of five
+characters) must be quoted with using ""@footnote{In Knuth's definition,
+the operand always starts at a fixed column number, and the use of
+quotation is therefore unnecessary. As @code{mixasm} releases this
+requirement, marking the beginning and end of the @code{ALF} operand
+disambiguates the parser's recognition of this operand when it includes
+blanks}.
+
+The workings of this sample program should be straightforward if you are
+familiar with MIXAL. See TAOCP vol. 1 for a thorought definition or
+@ref{MIX and MIXAL tutorial}, for a quick tutorial.
+
+@node Compiling, Running the program, Writing a source file, Getting started
+@comment node-name, next, previous, up
+@section Compiling
+@cindex compiling
+@cindex binary programs
+@cindex virtual machine
+@cindex assembler
+@cindex @code{mixasm}
+
+A simulator of the MIX computer, called @code{mixvm} (MIX virtual
+machine) is included in the @sc{mdk} tools. It is able to run binary
+files containing MIX instructions written in their binary
+representation. You can translate MIXAL source files into this binary
+form using @code{mixasm}, the MIXAL assembler. So, in order to compile
+the @file{hello.mixal} file, you can type the following
+command at your shell prompt:
+
+@example
+mixasm -g hello @key{RET}
+@end example
+
+If the source file contains no errors, this will produce a binary file
+called @file{hello.mix} which can be loaded and run by the MIX virtual
+machine. The @code{-g} flag tells the assembler to include debug
+information in the executable file (for a complete description of all
+the compilation options, see @ref{mixasm}.) Now, your are ready to run
+your first MIX program, as described in the following section.
+
+
+@node Running the program, , Compiling, Getting started
+@comment node-name, next, previous, up
+@section Running the program
+@cindex @code{mixvm}
+@cindex non-interactive mode
+@cindex interactive mode
+
+MIX is a mythical computer, so it is no use ordering it from your
+favorite hardware provider. @sc{mdk} provides a software simulator of
+the computer, though. It is called @code{mixvm}, which stands for
+@dfn{MIX virtual machine}. Using it, you can run your MIXAL programs,
+after compiling them with @code{mixasm} into binary @file{.mix}
+files. @code{mixvm} can be used either in @dfn{interactive} or
+@dfn{non-interactive} mode. In the second case, @code{mixvm} will load
+your program into memory, execute it (producing any output due to MIXAL
+@code{OUT} instructions present in the program), and exit when it
+encounters a @code{HLT} instruction. In interactive mode, you will enter
+a shell prompt which allows you issuing commands to the running virtual
+machine. This commands will permit you loading, running and debugging
+programs, as well as inspecting the MIX computer state (register
+contents, memory cells contents and so on).
+
+@menu
+* Non-interactive mode:: Running your programs non-interactively.
+* Interactive mode:: Running programs interactively.
+* Debugging:: Commands for debugging your programs.
+@end menu
+
+@node Non-interactive mode, Interactive mode, Running the program, Running the program
+@comment node-name, next, previous, up
+@subsection Non-interactive mode
+@cindex non-interactive mode
+
+To make @code{mixvm} work in non-interactive mode, use the @code{-r}
+flag. Thus, to run our @file{hello.mix} program, simply type
+
+@example
+mixvm -r hello @key{RET}
+@end example
+
+@noindent at your command prompt, and you will get the following output:
+
+@example
+MIXAL HELLO WORLD
+** Execution time: 11
+@end example
+
+@noindent Since our hello world program uses MIX's device number 19 as
+its output device (@pxref{Writing a source file}), the output is
+redirected to the shell's standard output. Had you used any other MIX
+output devices (disks, drums, line printer, etc.), @code{mixvm} would
+have created a file named after the device used (e.g. @file{disk4.dev})
+and written its output there. Note also that the virtual machine reports
+the execution time of the program, according to the (virtual) time spent
+in each of the binary instructions (@pxref{Execution times}).
+
+Sometimes, you will prefer to store the results of your program in MIX
+registers rather than writing them to a device. In such cases,
+@code{mixvm}'s @code{-d} flag is your friend: it makes @code{mixvm} to
+dump the contents of its registers and flags after executing the loaded
+program. For instance, typing the following command at your shell's
+prompt
+
+@example
+mixvm -d -r hello
+@end example
+
+@noindent you will obtain the following output:
+
+@example
+MIXAL HELLO WORLD
+** Execution time: 11
+rA: + 00 00 00 00 00 (0000000000)
+rX: + 00 00 00 00 00 (0000000000)
+rJ: + 00 00 (0000)
+rI1: + 00 00 (0000) rI2: + 00 00 (0000)
+rI3: + 00 00 (0000) rI4: + 00 00 (0000)
+rI5: + 00 00 (0000) rI6: + 00 00 (0000)
+Overflow: F
+Cmp: E
+@end example
+
+@noindent which, in addition to the program's outputs and execution
+time, gives you the contents of the MIX registers and the values of the
+overflow toggle and comparison flag (admittedly, rather uninteresting in
+our sample).
+
+As you can see, running programs non-interactively has many
+limitations. You cannot peek the virtual machine's memory contents, not
+to mention stepping through your program's instructions or setting
+breakpoints. Enter interactive mode.
+
+@node Interactive mode, Debugging, Non-interactive mode, Running the program
+@comment node-name, next, previous, up
+@subsection Interactive mode
+@cindex interactive mode
+
+To enter the MIX virtual machine interactive mode, simply type
+
+@example
+mixvm @key{RET}
+@end example
+
+@noindent at your shell command prompt. This command enters the
+@code{mixvm} command shell. You will be presented the following command
+prompt:
+
+@example
+MIX >
+@end example
+
+@noindent The virtual machine is initialised and ready to accept your
+commands. The @code{mixvm} command shell uses GNU's readline, so that
+you have at your disposal command completion (using @key{TAB}) and
+history functionality, as well as other line editing shortcuts common to
+all utilities using this library (for a complete description of
+readline's line editing usage, see @ref{Command Line
+Editing,,,Readline}.)
+
+Usually, the first thing you will want to do is loading a compiled MIX
+program into memory. This is acomplished by the @code{load} command,
+which takes as an argument the name of the @file{.mix} file to be
+loaded. Thus, typing
+
+@example
+MIX > load hello @key{RET}
+Program loaded. Start address: 3000
+MIX >
+@end example
+
+@noindent will load @file{hello.mix} into the virtual machine's memory
+and set the program counter to the address of the first instruction. You
+can obtain the contents of the program counter using the command
+@code{pc}:
+
+@example
+MIX > pc
+Current address: 3000
+MIX >
+@end example
+
+After loading it, you are ready to run the program, using, as you surely
+have guessed, the @code{run} command:
+
+@example
+MIX > run
+Running ...
+MIXAL HELLO WORLD
+... done
+Elapsed time: 11 /Total program time: 11 (Total uptime: 11)
+MIX >
+@end example
+
+@noindent Note that now the timing statistics are richer. You obtain the
+elapsed execution time (i.e., the time spent executing instructions
+since the last breakpoint), the total execution time for the program up
+to now (which in our case coincides with the elapsed time, since there
+were no breakpoints), and the total uptime for the virtual machine (you
+can load and run more than one program in the same session). After
+running the program, the program counter will point to the address after
+the one containing the @code{HLT} instruction. In our case, asking the
+value of the program counter after executing the program will give us
+
+@example
+MIX > pc
+Current address: 3002
+MIX >
+@end example
+
+@noindent You can check the contents of a memory cell giving its address
+as an argument of the command @code{pmem}, like this
+
+@example
+MIX > pmem 3001
+3001: + 00 00 00 02 05 (0000000133)
+MIX >
+@end example
+
+@noindent
+and convince yourself that address 3001 contains the binary
+representation of the instruction @code{HLT}. An address range of the
+form FROM-TO can also be used as the argument of @code{pmem}:
+
+@example
+MIX > pmem 3000-3006
+3000: + 46 58 00 19 37 (0786957541)
+3001: + 00 00 00 02 05 (0000000133)
+3002: + 14 09 27 01 13 (0237350989)
+3003: + 00 08 05 13 13 (0002118477)
+3004: + 16 00 26 16 19 (0268542995)
+3005: + 13 04 00 00 00 (0219152384)
+3006: + 00 00 00 00 00 (0000000000)
+MIX >
+@end example
+
+@noindent
+In a similar manner, you can look at the contents of the MIX registers
+and flags. For instance, to ask for the contents of the A register you
+can type
+
+@example
+MIX > preg A
+rA: + 00 00 00 00 00 (0000000000)
+MIX >
+@end example
+
+@noindent
+Use the comand @code{help} to obtain a list of all available commands,
+and @code{help COMMAND} for help on a specific command, e.g.
+
+@example
+MIX > help run
+run Run loaded or given MIX code file. Usage: run [FILENAME]
+MIX >
+@end example
+
+@noindent
+For a complete list of commands available at the MIX propmt,
+@xref{mixvm}. In the following subsection, you will find a quick tour
+over commands useful for debugging your programs.
+
+@node Debugging, , Interactive mode, Running the program
+@comment node-name, next, previous, up
+@subsection Debugging commands
+
+The interactive mode of @code{mixvm} lets you step by step execution of
+programs as well as breakpoint setting. Use @code{next} to step through
+the program, running its instructions one by one. To run our
+two-instruction @file{hello.mix} sample you can do the following:
+
+@example
+MIX > load hello
+Program loaded. Start address: 3000
+MIX > pc
+Current address: 3000
+MIX > next
+MIXAL HELLO WORLD
+Elapsed time: 1 /Total program time: 1 (Total uptime: 1)
+MIX > pc
+Current address: 3001
+MIX > next
+End of program reached at address 3002
+Elapsed time: 10 /Total program time: 11 (Total uptime: 11)
+MIX > pc
+Current address: 3002
+MIX > next
+MIXAL HELLO WORLD
+Elapsed time: 1 /Total program time: 1 (Total uptime: 12)
+MIX >
+MIX > run
+Running ...
+... done
+Elapsed time: 10 /Total program time: 11 (Total uptime: 22)
+MIX > @end example
+@noindent
+(As an aside, the above sample also shows how the virtual machine
+handles cummulative time statistics and automatic program restart).
+
+You can set a breakpoint at a given address using the command
+@code{sbpa} (set breakpoint at address). When a breakpoint is set,
+@code{run} will stop before executing the instruction at the given
+address. Typing @code{run} again will resume program execution. Coming
+back to our hello world example, we would have:
+
+@example
+MIX > sbpa 3001
+Breakpoint set at address 3001
+MIX > run
+Running ...
+MIXAL HELLO WORLD
+... stopped: breakpoint at line 8 (address 3001)
+Elapsed time: 1 /Total program time: 1 (Total uptime: 23)
+MIX > run
+Running ...
+... done
+Elapsed time: 10 /Total program time: 11 (Total uptime: 33)
+MIX >
+@end example
+
+@noindent
+Note that, since we compiled @file{hello.mixal} with debug info enabled
+(the @code{-g} flag of @code{mixasm}), the virtual machine is able to
+tell us the line in the source file corresponding to the breakpoint we
+are setting. As a matter of fact, you can directly set breakpoints at
+source code lines using the command @code{sbp LINE_NO}, e.g.
+
+@example
+MIX > sbp 4
+Breakpoint set at line 7
+MIX >
+@end example
+
+@noindent
+@code{sbp} sets the breakpoint at the first meaningful source code line;
+thus, in the above example we have requested a breakpoint at a line
+which does not correspond to a MIX instruction and the breakpoint is set
+at the first line containing a real instruction after the given one. To
+unset breakpoints, use @code{cbpa ADDRESS} and @code{cbp LINE_NO}, or
+@code{cabp} to remove all currently set breakpoints.
+
+MIXAL lets you define symbolic constants, either using the @code{EQU}
+pseudoinstruction or starting an instruction line with a label (which
+assigns to the label the value of the current memory address). Each
+MIXAL program has, therefore, an associated symbol table which you can
+inspect using the @code{psym} command. For our hello world sample, you
+will obtain the following output:
+
+@example
+MIX > psym
+START: 3000
+TERM: 19
+MSG: 3002
+MIX >
+@end example
+
+Other useful commands for debugging are @code{tron} (which turns on
+tracing of executed intructions) and @code{weval} (which evaluates
+w-expressions on the fly). For a complete description of all available
+MIX commands, @xref{mixvm}.
diff --git a/doc/mdk_index.texi b/doc/mdk_index.texi
new file mode 100644
index 0000000..cb752f0
--- /dev/null
+++ b/doc/mdk_index.texi
@@ -0,0 +1,10 @@
+@node Concept Index, , Problems, Top
+@unnumbered Concept Index
+
+@cindex tail recursion
+@printindex cp
+
+@c @node MIXAL instructions, , Concept Index, Top
+@comment node-name, next, previous, up
+@c @unnumbered MIXAL instructions
+@c @printindex fn
diff --git a/doc/mdk_install.texi b/doc/mdk_install.texi
new file mode 100644
index 0000000..78690ba
--- /dev/null
+++ b/doc/mdk_install.texi
@@ -0,0 +1,180 @@
+@node Installing MDK, MIX and MIXAL tutorial, Introduction, Top
+@comment node-name, next, previous, up
+@chapter Installing @sc{mdk}
+
+@menu
+* Download::
+* Requirements::
+* Basic installation::
+* Emacs support::
+* Special configure flags::
+@end menu
+
+@node Download, Requirements, Installing MDK, Installing MDK
+@comment node-name, next, previous, up
+@section Download the source tarball
+
+GNU @sc{mdk} is distributed as a source tarball available for download in
+the following @acronym{URL}s:
+
+@itemize @bullet
+@item
+@url{ftp://ftp.gnu.org/pub/gnu/mdk} (or one of
+@uref{http://www.gnu.org/prep/ftp.html, its mirrors})
+@item
+@uref{http://sourceforge.net/project/showfiles.php?group_id=13897}
+@end itemize
+
+The above sites contain the latest stable releases of @sc{mdk}. The
+development branch is available at:
+
+@itemize @bullet
+@item
+@uref{http://sourceforge.net/cvs/?group_id=13897}
+@end itemize
+
+After you have downloaded the source tarball, unpack it in a directory
+of your choice using the command:
+
+@example
+tar xfvz mdk-X.Y.tar.gz
+@end example
+
+@noindent
+where @var{X.Y} stands for the downloaded version (the current stable
+release being version @value{VERSION}).
+
+@node Requirements, Basic installation, Download, Installing MDK
+@comment node-name, next, previous, up
+@section Requirements
+
+In order to build and install @sc{mdk}, you will need the following
+libraries installed in your system:
+
+@itemize @minus
+@item
+@uref{http://www.gtk.org, GLIB 1.2.0} (required)
+@item
+@uref{http://www.gnu.org/software/flex/flex.html, GNU Flex 2.3} (required)
+@item
+@uref{http://www.gtk.org, GTK+ 1.2.0} (optional)
+@item
+@uref{ftp://ftp.gnome.org/pub/GNOME/stable/sources/libglade/, libglade}
+(optional)
+@item
+GNU readline and history libraries (optional)
+@end itemize
+
+If present, readline and history are used to provide command completion
+and history management to the command line MIX virtual machine, @code{mixvm}
+GTK+ and libglade are needed if you want to build the graphical
+interface to the MIX virtual machine, @code{gmixvm}.
+
+@strong{Please note}: you need both the libraries @emph{and} the
+headers; this means both the library package and the @file{-dev} package
+if you do not compile your libraries yourself (ex: installing
+@file{libgtk1.2} and @file{libgtk1.2-dev} on Debian).
+
+@node Basic installation, Emacs support, Requirements, Installing MDK
+@comment node-name, next, previous, up
+@section Basic installation
+
+@sc{mdk} uses GNU Autoconf and Automake tools, and, therefore, should
+be built and installed without hassle using the following commands
+inside the source directory:
+
+@example
+./configure
+make
+make install
+@end example
+
+@noindent
+where the last one must be run as root.
+
+The first command, @code{configure}, will setup the makefiles for your
+system. In particular, @code{configure} will look for GTK+ and libglade,
+and, if they are present, will generate the appropiate makefiles for
+building the @code{gmixvm} graphical user interface. Upon completion,
+you should see a message with the configuration results like the
+following:
+
+@example
+*** GNU MDK 0.3 has been successfully configured. ***
+
+Type make to build the following utilities:
+ - mixasm (MIX assembler)
+ - mixvm (MIX virtual machine, with readline support)
+ - gmixvm (mixvm GTK+ GUI)
+@end example
+
+@noindent
+where the last line may be missing if you lack the above mentioned
+libraries.
+
+The next command, @code{make}, will actually build the @sc{mdk} programs
+in the following locations:
+
+@itemize @minus
+@item
+@file{mixutils/mixasm}
+@item
+@file{mixutils/mixvm}
+@item
+@file{mixgtk/gmixvm}
+@end itemize
+
+You can run these programs from within their directories, but I
+recommend you to install them in proper locations using @code{make
+install} from a root shell.
+
+@node Emacs support, Special configure flags, Basic installation, Installing MDK
+@comment node-name, next, previous, up
+@section Emacs support
+
+@code{mixvm} can be run within an Emacs GUD buffer using the elisp
+program @file{misc/mixvm.el}, kindly contributed by @value{PHILIP}.
+
+@file{mixvm.el} provides an interface between @sc{mdk}'s @code{mixvm}
+and Emacs, via @acronym{GUD}. Place this file in your load-path,
+optionally adding the following line to your @file{.emacs} file:
+
+@lisp
+(autoload 'mixvm "mixvm" "mixvm/gud interaction" t)
+@end lisp
+
+
+
+@node Special configure flags, , Emacs support, Installing MDK
+@comment node-name, next, previous, up
+@section Special configure flags
+
+You can fine tunning the configuration process using the following
+switches with configure:
+
+@defopt --enable-gui[=yes|no]
+@defoptx --disable-gui
+Enables/disables the built of the MIX virtual machine GUI
+(@code{gmixvm}). If the required libraries are missing
+(@pxref{Requirements}) the configure script with automatically disable
+this feature.
+@end defopt
+
+@defopt --with-readline[=yes|no]
+@defoptx --without-readline
+Enables/disables the GNU Readline support for @code{mixvm}. If the
+required libraries are missing (@pxref{Requirements}) the configure
+script with automatically disable this feature.
+@end defopt
+
+For additional, boilerplate configure options, see the @file{INSTALL}
+file, or run
+
+@example
+configure --help
+@end example
+
+
+
+
+
diff --git a/doc/mdk_intro.texi b/doc/mdk_intro.texi
new file mode 100644
index 0000000..2a3f95d
--- /dev/null
+++ b/doc/mdk_intro.texi
@@ -0,0 +1,48 @@
+@node Introduction, Installing MDK, Top, Top
+@comment node-name, next, previous, up
+@unnumbered Introduction
+@cindex Introduction
+
+In his book series @cite{The Art of Computer Programming} (published by
+Addison Wesley), D. Knuth uses an imaginary computer, the MIX, and its
+associated machine-code and assembly languages to ilustrate the
+concepts and algorithms as they are presented.
+
+The MIX's architecture is a simplified version of those found in real
+CISC CPUs, and the MIX assembly language (MIXAL) provides a set of
+primitives that will be very familiar to any person with a minimum
+experience in assembly programming. The MIX/MIXAL definition is powerful
+and complete enough to provide a virtual development platform for
+writing quite complex programs, and close enough to real computers to be
+worth using when learning programming techniques. At any rate, if you
+want to learn or improve your programming skills, a MIX development
+environment would come in handy.
+
+The @sc{mdk} package aims at providing such virtual development
+environment on a GNU box. Thus, @sc{mdk} offers you a set of utilities
+to simulate the MIX computer and to write, compile, run and debug MIXAL
+programs. As of version @value{VERSION}, @sc{mdk} includes
+the following programs:
+
+@table @code
+@item mixasm
+MIXAL assembler. Assembler which translates MIXAL source files into
+programs that can be run (and debugged) by @code{mixvm} or @code{gmixvm}.
+@item mixvm
+MIX virtual machine. Emulation of the MIX computer with a @acronym{CLI}.
+@item gmixvm
+A GTK+ GUI for the MIX virtual machine. Provides all of @code{mixvm}
+functionality accessible through a graphical interface.
+@item mixvm.el
+This elisp program allows running @code{mixvm} inside an Emacs GUD
+buffer, allowing concurrent edition and debugging of MIXAL programs.
+@end table
+
+@code{mixvm} and @code{gmixvm} implement a simulator of the MIX
+computer, giving you a virtual machine for executing and debugging MIX
+programs. These binary programs could be written by hand, but it is
+easier to produce them compiling MIXAL source files, using the MIXAL
+assembler @code{mixasm}.
+
+This manual gives you a tutorial of MIX and MIXAL, and a thorough
+description of the use of the @sc{mdk} utilities.
diff --git a/doc/mdk_mixasm.texi b/doc/mdk_mixasm.texi
new file mode 100644
index 0000000..753aa33
--- /dev/null
+++ b/doc/mdk_mixasm.texi
@@ -0,0 +1,79 @@
+@node mixasm, Copying, gmixvm, Top
+@comment node-name, next, previous, up
+@chapter @code{mixasm}, the MIXAL assembler
+@cindex @code{mixasm}
+@cindex MIXAL
+@cindex assembler
+
+MIX programs, as executed by @code{mixvm}, are composed of binary
+instructions loaded into the virtual machine memory as MIX
+words. Although you could write your MIX programs directly as a series
+of words in binary format, you have at your disposal a more friendly
+assembly language, MIXAL (@pxref{MIXAL}) which is compiled into binary
+form by @code{mixasm}, the MIXAL assembler included in @sc{mdk}. In this
+chapter, you will find a complete description of @code{mixasm} options.
+
+@menu
+* Invoking @code{mixasm}:: @code{mixasm} options
+@end menu
+
+@node Invoking @code{mixasm}, , mixasm, mixasm
+@comment node-name, next, previous, up
+@section Invoking @code{mixasm}
+
+In its simplest form, @code{mixasm} is invoked with a single argument,
+which is the name of the MIXAL file to be compiled, e.g.
+
+@example
+mixasm hello
+@end example
+
+@noindent
+will compile either @file{hello} or @file{hello.mixal}, producing a
+binary file named @file{hello.mix} if no errors are found.
+
+In addition, @code{mixasm} can be invoked with the following command
+line options (note, that, following GNU's conventions, we provide a long
+option name for each available single letter switch):
+
+@example
+mixasm [-vhulg] [-o OUTPUT_FILE] [--version] [--help]
+ [--usage] [--debug] [--output=OUTPUT_FILE] [--list[=LIST_FILE]] file
+@end example
+
+@noindent
+The meaning of these options is as follows:
+
+@defopt -v
+@defoptx --version
+Prints version and copyleft information and exits.
+@end defopt
+
+@defopt -h
+@defoptx --help
+@defoptx -u
+@defoptx --usage
+Prints a summary of available options and exits.
+@end defopt
+
+@defopt -g
+@defoptx --debug
+Includes debugging information in the compiled file, allowing breakpoint
+setting at source level and symbol table inspection under @code{mixvm}.
+@end defopt
+
+@defopt -o output_file
+@defoptx --output=output_file
+By default, the given source file @var{file.mixal} is compiled into
+@var{file.mix}. You can provide a different name for the output file
+using this option.
+@end defopt
+
+@defopt -l
+@defoptx --list[=list_file]
+This option causes @code{mixasm} to produce, in addion to the
+@file{.mix} file, an ASCII file containing a summary of the compilation
+results. The file is named after the MIXAL source file, changing its
+extension to @file{.mls} if no argument is provided; otherwise, the
+listing file is named according to the argument.
+@end defopt
diff --git a/doc/mdk_mixvm.texi b/doc/mdk_mixvm.texi
new file mode 100644
index 0000000..8289472
--- /dev/null
+++ b/doc/mdk_mixvm.texi
@@ -0,0 +1,478 @@
+@node mixvm, gmixvm, mixvm.el, Top
+@comment node-name, next, previous, up
+@chapter @code{mixvm}, the MIX computer simulator
+
+@cindex mixvm
+
+This chapter describes @code{mixvm}, the MIX computer
+simulator. @code{mixvm} is a command line interface programme which
+simulates the MIX computer (@pxref{The MIX computer}). It is able
+to run MIXAL programs (@pxref{MIXAL}) previously compiled with the MIX
+assembler (@pxref{mixasm}). The simulator allows inspection of the MIX
+computer components (registers, memory cells, comparison flag and overflow
+toggle), step by step execution of MIX programmes, and breakpoint
+setting to aid you in debugging your code. For a tutorial description of
+@code{mixvm} usage, @xref{Running the program}.
+
+@menu
+* Invocation:: Options when invoking @code{mixvm}.
+* Commands:: Commands available in interactive mode.
+* Devices:: MIX block devices implementation.
+@end menu
+
+@node Invocation, Commands, mixvm, mixvm
+@comment node-name, next, previous, up
+@section Invoking @code{mixvm}
+
+@code{mixvm} can be invoked with the following command line options
+(note, that, following GNU's conventions, we provide a long option name
+for each available single letter switch):
+
+@example
+mixvm [-vhurd] [--version] [--help] [--usage] [--run] [--dump]
+ [FILE[.mix]]
+@end example
+
+@noindent
+The meaning of these options is as follows:
+
+@defopt -v
+@defoptx --version
+Prints version and copyleft information and exits.
+@end defopt
+
+@defopt -h
+@defoptx --help
+@defoptx -u
+@defoptx --usage
+Prints a summary of available options and exits.
+@end defopt
+
+@defopt -r
+@defoptx --run
+Loads the specified @var{FILE} and executes it. After the program
+execution, @code{mixvm} exits. @var{FILE} must be the name of a binary
+@file{.mix} program compiled with @code{mixasm}. If your program does
+not produce any output, use the @code{-d} flag (see below) to peek at
+the virtual machine's state after execution.
+@end defopt
+
+@defopt -d
+@defoptx --dump
+This option must be used in conjuction with @code{-r}, and tells
+@code{mixvm} to print the value of the virtual machine's registers,
+comparison flag and overflow toggle after executing the program named
+@var{FILE}. See @xref{Non-interactive mode}, for sample usage.
+@end defopt
+
+When run without the @code{-r} flag, @code{mixvm} enters its interactive
+mode, showing you a prompt like this one:
+
+@example
+MIX >
+@end example
+
+@noindent
+and waiting for your commands (@pxref{Commands}). If the
+optional @var{FILE} argument is given, the file @file{FILE.mix} will be
+loaded into the virtual machine memory before entering the interactive
+mode.
+
+@node Commands, Devices, Invocation, mixvm
+@comment node-name, next, previous, up
+@section Interactive commands
+
+You can enter the interactive mode of the MIX virtual machine by simply
+invoking @code{mixvm} without arguments. You will then presented a shell
+prompt
+
+@example
+MIX >
+@end example
+
+@noindent
+which indicates that a new virtual machine has been initialised and is
+ready to execute your commands. As we have already mentioned, this
+command prompt offers you command line editing facilities which are
+described in the Readline user's manual (chances are that you are
+already familiar with these command line editing capabilities, as they
+are present in many GNU utilities, e.g. the @code{bash} shell). As a
+beginner, your best friend will be the @code{help} command, which shows
+you a summary of all available MIX commands and their usage; its syntax
+is as follows:
+
+@deffn {@code{mixvm} command} help [command]
+@deffnx {@code{mixvm} command} ? [command]
+Prints a short description of the given @var{command} and its usage. If
+@var{command} is omitted, all available commands are described.
+@end deffn
+
+@menu
+* File commands:: Loading and executing programs.
+* Debug commands:: Debugging programs.
+* State commands:: Inspecting the virtual machine state.
+@end menu
+
+@node File commands, Debug commands, Commands, Commands
+@comment node-name, next, previous, up
+@subsection File commands
+
+You have at your disposal a series of commands that let you load and
+execute MIX executable files, as well as manipulate MIXAL source files:
+
+@deffn {file command} load file[.mix]
+This command loads a binary file, @var{file.mix} into the virtual
+machine memory, and positions the program counter at the beginning of
+the loaded program. This address is indicated in the MIXAL source file
+as the operand of the @code{END} pseudoinstruction. Thus, if your
+@file{sample.mixal} source file contains the line:
+
+@example
+ END 3000
+@end example
+
+@noindent
+and you compile it with @code{mixasm} to produce the binary file
+@file{sample.mix}, you will load it into the virtual machine as follows:
+
+@example
+MIX > load sample
+Program loaded. Start address: 3000
+MIX >
+@end example
+
+@end deffn
+
+@deffn {file command} run [file[.mix]]
+When executed without argument, this command initiates or resumes
+execution of instructions from the current program counter
+address. Therefore, issuing this command after a successful @code{load},
+will run the loaded program until either a @code{HLT} instruction or a
+breakpoint is found. If you provide a MIX filename as argument, the
+given file will be loaded (as with @code{load} @var{file}) and
+executed. If @code{run} is invoked again after program execution
+completion (i.e., after the @code{HLT} instruction has been found in a
+previous run), the program counter is repositioned and execution starts
+again from the beginning.
+@end deffn
+
+@deffn {file command} edit file[.mixal]
+The source file @var{file.mixal} is edited using the editor defined in
+the environment variable @var{MDK_EDITOR}. If this variable is not set,
+the following ones are tried out in order: @var{X_EDITOR}, @var{EDITOR}
+and @var{VISUAL}.
+@end deffn
+
+@deffn {file command} compile file[.mixal]
+The source file @var{file.mixal} is compiled (with debug information
+enabled) using @code{mixasm}.
+@end deffn
+
+
+@node Debug commands, State commands, File commands, Commands
+@comment node-name, next, previous, up
+@subsection Debug commands
+
+Sequential execution of loaded programs can be interrupted using the
+following debug commands:
+
+@deffn {debug command} next [ins_number]
+This command causes the virtual machine to fetch and execute up to
+@var{ins_number} instructions, beginning from the current program
+counter position. Execution is interrupted either when the specified
+number of instructions have been fetched or a breakpoint is found,
+whatever happens first. If run without arguments, one instruction is
+executed.
+@end deffn
+
+@deffn {debug command} sbp line_number
+Sets a breakpoint at the specified source file line number. If the line
+specified corresponds to a command or to a MIXAL pseudoinstruction which
+does not produce a MIX instruction in the binary file (such as
+@code{ORIG} or @code{EQU}) the breakpoint is set at the first source
+code line giving rise to a MIX instruction after the specified
+one. Thus, for our sample @file{hello.mixal} file:
+
+@example
+* (1)
+* hello.mixal: say 'hello world' in MIXAL (2)
+* (3)
+* label ins operand comment (4)
+TERM EQU 19 the MIX console device number (5)
+ ORIG 1000 start address (6)
+START OUT MSG(TERM) output data at address MSG (7)
+...
+@end example
+
+@noindent
+trying to set a breakpoint at line 5, will produce the following result:
+
+@example
+MIX > sbp 5
+Breakpoint set at line 7
+MIX >
+@end example
+
+@noindent
+since line 7 is the first one compiled into a MIX instruction (at
+address 3000). In order to @code{sbp} to work, the source file must be
+compiled using the @code{-g} flags, which tells @code{mixasm} to include
+debug information in the binary @file{.mix} file.
+@end deffn
+
+@deffn {debug command} spba address
+Sets a breakpoint at the given memory @var{address}. The argument must
+be a valid MIX memory address, i.e., it must belong into the range
+@w{[0-3999]}. Note that no check is performed to verify that the
+specified address is reachable during program execution. No debug
+information is needed to set a breakpoint by address with @code{sbpa}.
+@end deffn
+
+@deffn {debug command} cbp line_no
+Clears a (previously set) breakpoint at the given source file line.
+@end deffn
+
+@deffn {debug command} cbpa address
+Clears a (previously set) breakpoint at the given memory address.
+@end deffn
+
+@deffn {debug command} cabp
+Clears all currently set breakpoints.
+@end deffn
+
+@deffn {debug command} psym [symbol_name]
+MIXAL programs can define symbolic constants, using either the
+@code{EQU} pseudoinstruction or a label at the beginning of a
+line. Thus, in the program fragment
+
+@example
+VAR EQU 2168
+ ORIG 4000
+START LDA VAR
+@end example
+
+@noindent
+the symbol @code{VAR} stands for the value 2168, while @code{START} is
+assigned the value 4000. When MIXAL programs are compiled using the
+@code{-g} flag (which tells @code{mixasm} to include debug information
+in the binary @file{.mix} file), the symbol table can be consulted from
+the @code{mixvm} command line using @code{psym} followed by the name of
+the symbol whose contents you are interested in. When run without
+arguments, @code{psym} will print all defined symbols and their values.
+@end deffn
+
+The virtual machine can also show you the instructions it is executing,
+using the following commands:
+
+@deffn {debug command} tron
+@deffnx troff
+@code{tron} enables instruction tracing. When tracing is enabled, each
+time the virtual machine executes an instruction (due to your issuing a
+@code{run} or @code{next} command), it is printed in its canonical form
+(that is, with all expressions evaluated to their numerical values) and,
+if the program was compiled with debug information, as it was originally
+typed in the MIXAL source file. Instruction tracing is disable with the
+@code{troff} command. A typical tracing session could be like this:
+
+@example
+MIX > tron
+Instruction tracing has been turned ON.
+MIX > next
+3000: [OUT 3002,0(2:3)] START OUT MSG(TERM)
+MIXAL HELLO WORLD
+Elapsed time: 1 /Total program time: 1 (Total uptime: 1)
+MIX > next
+3001: [HLT 0,0] HLT
+End of program reached at address 3002
+Elapsed time: 10 /Total program time: 11 (Total uptime: 11)
+MIX > troff
+Instruction tracing has been turned OFF.
+MIX >
+@end example
+@noindent
+The executed instruction, as it was translated, is shown between square
+brackets after the memory address, and, following it, you can see the
+actual MIXAL code that was compiled into the executed instruction.
+@end deffn
+
+@code{mixvm} is also able of evaluating w-expressions
+(@pxref{W-expressions}) using the following command:
+
+@deffn {debug command} weval WEXP
+Evaluates the given w-expression, @var{WEXP}. The w-expression can
+contain any currently defined symbol. For instance:
+
+@example
+MIX > psym START
++ 00 00 00 46 56 (0000003000)
+MIX > weval START(0:1),START(3:4)
++ 56 00 46 56 00 (0939716096)
+MIX >
+@end example
+@end deffn
+
+New symbols can be defined using the @code{ssym} command:
+@deffn {debug command} ssym SYM WEXP
+Defines the symbol named @var{SYM} with the value resulting from
+evaluating @var{WEXP}, an w-expression. The newly defined symbol can be
+used in subsequent @code{weval} commands, as part of the expression to
+be evaluated. E.g.,
+
+@example
+MIX > ssym S 2+23*START
++ 00 00 18 19 56 (0000075000)
+MIX > psym S
++ 00 00 18 19 56 (0000075000)
+MIX > weval S(3:4)
++ 00 00 19 56 00 (0000081408)
+MIX >
+@end example
+@end deffn
+
+Finally, if you want to discover which is the decimal value of a MIX
+word expressed as five bytes plus sign, you can use
+
+@deffn {debug command} w2d WORD
+Computes the decimal value of the given word. @var{WORD} must be
+expressed as a sign (+/-) followed by five space-delimited, two-digit
+decimal values representing the five bytes composing the word. The
+reverse operation (showing the word representation of a decimal value)
+can be accomplished with @code{weval}. For instance:
+
+@example
+MIX > w2d - 01 00 00 02 02
+-16777346
+MIX > weval -16777346
+- 01 00 00 02 02 (0016777346)
+MIX >
+@end example
+@end deffn
+
+@node State commands, , Debug commands, Commands
+@comment node-name, next, previous, up
+@subsection State commands
+
+Inspection and modification of the virtual machine state (memory,
+registers, overflow toggle and comparison flag contents) is accomplished
+using the following commands:
+
+@deffn {state command} pc
+Prints the current value of the program counter, which stores the
+address of the next instruction to be executed in a non-halted program.
+@end deffn
+
+@deffn {state command} preg [A | X | J | I[1-6]]
+@deffnx {state command} pall
+@deffnx {state command} sreg A | X | J | I[1-6] value
+@code{preg} prints the contents of a given MIX register. For instance,
+@w{@code{preg} @var{A}} will print the contents of the A-register. When
+invoked without arguments, all registers shall be printed:
+
+@example
+MIX > preg
+rA: - 00 00 00 00 35 (0000000035)
+rX: + 00 00 00 15 40 (0000001000)
+rJ: + 00 00 (0000)
+rI1: + 00 00 (0000) rI2: + 00 00 (0000)
+rI3: + 00 00 (0000) rI4: + 00 00 (0000)
+rI5: + 00 00 (0000) rI6: + 00 00 (0000)
+MIX >
+@end example
+
+As you can see in the above sample, the contents is printed as the sign
+plus the values of the MIX bytes stored in the register and, between
+parenthesis, the decimal representation of its module.
+
+@code{pall} prints the contents of all registers plus the comparison
+flag and overflow toggle.
+
+Finally, @code{sreg} Sets the contents of the given register to
+@var{value}, expressed as a decimal constant. If @var{value} exceeds the
+maximum value storable in the given register, @math{VALUE mod
+MAXIMU_VALUE} is stored, e.g.
+
+@example
+MIX > sreg I1 1000
+MIX > preg I1
+rI1: + 15 40 (1000)
+MIX > sreg I1 1000000
+MIX > preg I1
+rI1: + 09 00 (0576)
+MIX >
+@end example
+
+@end deffn
+
+
+@deffn {state command} pflags
+@deffnx {state command} scmp E | G | L
+@deffnx {state command} sover F | T
+@code{pflags} prints the value of the comparison flag and overflow
+toggle of the virtual machine, e.g.
+
+@example
+MIX > pflags
+Overflow: F
+Cmp: E
+MIX >
+@end example
+
+@noindent
+The values of the overflow toggle are either @var{F} (false) or @var{T}
+(true), and, for the comparison flag, @var{E}, @var{G}, @var{L} (equal,
+greater, lesser). @code{scmp} and @code{sover} are setters of the
+comparison flag and overflow toggle values.
+@end deffn
+
+@deffn {state command} pmem from[-to]
+@deffnx {state command} smem address value
+@code{pmem} prints the contents of memory cells in the address range
+@w{[@var{FROM}-@var{TO}]}. If the upper limit @var{to} is omitted, only
+the contents of the memory cell with address @var{FROM} is printed, as
+in
+
+@example
+MIX > pmem 3000
+3000: + 46 58 00 19 37 (0786957541)
+MIX >
+@end example
+
+The memory contents is displayed both as the set of five MIX bytes plus
+sign composing the stored MIX word and, between parenthesis, the decimal
+representation of the module of the stored value.
+
+@code{smem} sets the content of the memory cell with address
+@var{address} to @var{value}, expressed as a decimal constant.
+
+@end deffn
+
+Finally, you can use the @code{quit} command to exit @code{mixvm}.
+
+@node Devices, , Commands, mixvm
+@comment node-name, next, previous, up
+@section MIX block devices
+
+The MIX computer comes equipped with a set of block devices for
+input-output operations (@pxref{Input-output operators}). @code{mixvm}
+implements these block devices as disk files, with the exception of
+block device no. 19 (typewriter terminal) which is redirected to
+standard output. When you request an output operation on any other
+(output) device, a file named according to the following table will be
+created in the current directory, and the specified MIX words will be
+written to the file in binary form (for binary devices) or in ASCII (for
+char devices). Files corresponding to input block devices should be
+created and filled beforehand to be used by the MIX virtual machine (for
+input-output devices this creation can be accomplished by a MIXAL
+program writing to the device the required data, or, if you prefer, with
+your favourite editor).
+
+@multitable {the device name} { xx-xx } {filename[x-x].dev} {bin i/o }
+@item @emph{Device} @tab @emph{No.} @tab @emph{filename} @tab @emph{type}
+@item Tape @tab 0-7 @tab @file{tape[0-7].dev} @tab bin i/o
+@item Disks @tab 8-15 @tab @file{disk[0-7].dev} @tab bin i/o
+@item Card reader @tab 16 @tab @file{cardrd.dev} @tab char in
+@item Card writer @tab 17 @tab @file{cardwr.dev} @tab char out
+@item Line printer @tab 18 @tab @file{printer.dev} @tab char out
+@item Terminal @tab 19 @tab @code{stdout} @tab char out
+@item Paper tape @tab 20 @tab @file{paper.dev} @tab char out
+@end multitable
diff --git a/doc/mdk_tut.texi b/doc/mdk_tut.texi
new file mode 100644
index 0000000..12bfb42
--- /dev/null
+++ b/doc/mdk_tut.texi
@@ -0,0 +1,1259 @@
+@node MIX and MIXAL tutorial, Getting started, Installing MDK, Top
+@comment node-name, next, previous, up
+@chapter MIX and MIXAL tutorial
+@cindex MIX
+@cindex MIXAL
+
+In the book series @cite{The Art of Computer Programming}, by D. Knuth,
+a virtual computer, the MIX, is used by the author (together with the
+set of binary instructions that the virtual CPU accepts) to illustrate
+the algorithms and skills that every serious programmer should
+master. Like any other real computer, there is a symbolic assembler
+language that can be used to program the MIX: the MIX assembly language,
+or MIXAL for short. In the following subsections you will find a tutorial
+on these topics, which will teach you the basics of the MIX architecture
+and how to program a MIX computer using MIXAL.
+
+@menu
+* The MIX computer:: Architecture and instruction set
+ of the MIX computer.
+* MIXAL:: The MIX assembly language.
+@end menu
+
+@node The MIX computer, MIXAL, MIX and MIXAL tutorial, MIX and MIXAL tutorial
+@comment node-name, next, previous, up
+@section The MIX computer
+
+In this section, you will find a description of the MIX computer,
+its components and instruction set.
+
+@menu
+* MIX architecture::
+* MIX instruction set::
+@end menu
+
+@node MIX architecture, MIX instruction set, The MIX computer, The MIX computer
+@comment node-name, next, previous, up
+@subsection MIX architecture
+@cindex byte
+@cindex MIX byte
+@cindex word
+@cindex MIX word
+@cindex MIX architecture
+@cindex MIX computer
+@cindex register
+@cindex MIX register
+@cindex field specification
+@cindex fspec
+@cindex instruction
+@cindex MIX instruction
+@cindex address
+@cindex memory cell
+@cindex cell
+@cindex memory
+@cindex index
+
+The basic information storage unit in the MIX computer is the
+@dfn{byte}, which stores positive values in the range 0-63 . Note that a
+MIX byte can be then represented as 6 bits, instead of the common 8 bits
+for a @emph{regular} byte. Unless otherwise stated, we shall use the
+word @dfn{byte} to refer to a MIX 6-bit byte.
+
+A MIX @dfn{word} is defined as a set of 5 bytes plus a sign. The bytes
+within a word are numbered from 1 to 5, being byte number one the most
+significant one. The sign is denoted by index 0. Graphically,
+
+@example
+ -----------------------------------------------
+| 0 | 1 | 2 | 3 | 4 | 5 |
+ -----------------------------------------------
+| +/- | byte | byte | byte | byte | byte |
+ -----------------------------------------------
+@end example
+@noindent
+Sample MIX words are @samp{- 12 00 11 01 63} and @samp{+ 12 11 34 43
+00}.
+
+You can refer to subfields within a word using a @dfn{field
+specification} or @dfn{fspec} of the form ``(@var{l}:@var{r})'', where
+@var{l} denotes the first byte, and @var{r} the last byte of the
+subfield.
+When @var{l} is zero, the subfield includes the word's
+sign. An fspec can also be represented as a single value @code{F}, given
+by @code{F = 8*L + R} (thus the fspec @samp{(1:3)}, denoting the first
+three bytes of a word, is represented by the integer 11).
+
+The MIX computer stores information in @dfn{registers}, that can store
+either a word or two bytes and sign (see below), and @dfn{memory cells},
+each one containing a word. Specifically, the MIX computer has 4000
+memory cells with addresses 0 to 3999 (i.e., two bytes are enough to
+address a memory cell) and the following registers:
+
+@cindex rA
+@cindex rX
+@cindex rJ
+@cindex rIn
+@cindex register
+
+@table @asis
+@item @code{rA}
+A register. General purpose register holding a word. Usually its
+contents serves as the operand of arithmetic and storing instructions.
+@item @code{rX}
+X register. General purpose register holding a word. Often it acts as an
+extension or a replacement of @samp{rA}.
+@item @code{rJ}
+J (jump) register. This register stores positive two-byte values,
+usually representing a jump address.
+@item @code{rI1}, @code{rI2}, @code{rI3}, @code{rI4}, @code{rI5}, @code{rI6}
+Index registers. These six registers can store a signed two-byte
+value. Their contents is used as indexing values for the computation of
+effective memory addresses.
+@end table
+
+@cindex @sc{ov}
+@cindex @sc{cm}
+@cindex @code{un}
+@cindex overflow toggle
+@cindex comparison indicator
+@cindex input-output devices
+@noindent
+In addition, the MIX computer contains:
+
+@itemize @minus
+@item
+An @dfn{overflow toggle} (a single bit with values @dfn{on} or
+@dfn{off}). In this manual, this toggle is denoted @sc{ov}.
+@item
+A @dfn{comparison indicator} (having three values: @dfn{EQUAL},
+@dfn{GREATER} or @dfn{LESS}). In this manual, this indicator is denoted
+@sc{cm}, and its possible values are abbreviated as @dfn{E}, @dfn{G} and
+@dfn{L}.
+@item
+Input-output block devices. Each device is labelled as @code{un}, where
+@code{n} runs from 0 to 20. In Knuth's definition, @code{u0} through
+@code{u7} are magnetic tape units, @code{u8} through @code{15} are disks
+and drums, @code{u16} is a card reader, @code{u17} is a card writer,
+@code{u18} is
+a line printer and, @code{u19} is a typewriter terminal, and @code{u20},
+a paper tape. Our implementation maps these devices to disk files,
+except for @code{u19}, which represents the standard output.
+@end itemize
+
+As noted above, the MIX computer communicates with the external world by
+a set of input-output devices which can be ``connected'' to it. The
+computer interchanges information using blocks of words whose length
+depends on the device at hand (@pxref{Devices}). These words are
+interpreted by the device either as binary information (for devices
+0-16), or as representing printable characters (devices 17-20). In the
+last case, each MIX byte is mapped onto a character according to the
+following table:
+
+@multitable {00} {C} {00} {C} {00} {C} {00} {C}
+@item 00 @tab @tab 01 @tab A @tab 02 @tab B @tab 03 @tab C
+@item 04 @tab D @tab 05 @tab E @tab 06 @tab F @tab 07 @tab G
+@item 08 @tab H @tab 09 @tab I @tab 10 @tab d @tab 11 @tab J
+@item 12 @tab K @tab 13 @tab L @tab 14 @tab M @tab 15 @tab N
+@item 16 @tab O @tab 17 @tab P @tab 18 @tab Q @tab 19 @tab R
+@item 20 @tab s @tab 21 @tab p @tab 22 @tab S @tab 23 @tab T
+@item 24 @tab U @tab 25 @tab V @tab 26 @tab W @tab 27 @tab X
+@item 28 @tab Y @tab 29 @tab Z @tab 30 @tab 0 @tab 31 @tab 1
+@item 32 @tab 2 @tab 33 @tab 3 @tab 34 @tab 4 @tab 35 @tab 5
+@item 36 @tab 6 @tab 37 @tab 7 @tab 38 @tab 8 @tab 39 @tab 9
+@item 40 @tab . @tab 41 @tab , @tab 42 @tab ( @tab 43 @tab )
+@item 44 @tab + @tab 45 @tab - @tab 46 @tab * @tab 47 @tab /
+@item 48 @tab = @tab 49 @tab $ @tab 50 @tab < @tab 51 @tab >
+@item 52 @tab @@ @tab 53 @tab ; @tab 54 @tab : @tab 55 @tab '
+@end multitable
+@noindent
+The value 0 represents a whitespace. Lowercase letters (d, s, p)
+correspond to symbols not representable as ASCII characters (uppercase
+delta, sigma and gamma, respectively), and byte values 56-63 have no
+associated character.
+
+Finally, the MIX computer features a virtual CPU which controls the
+above components, and which is able to execute a rich set of
+instructions (constituting its machine language, similar to those
+commonly found in real CPUs), including arithmetic, logical, storing,
+comparison and jump instructions. Being a typical von Neumann computer,
+the MIX CPU fetchs binary instructions from memory sequentially (unless
+a jump instruction is found), and stores the address of the next
+instruction to be executed in an internal register called @dfn{location
+counter} (also known as program counter in other architectures).
+
+The next section, @xref{MIX instruction set}, gives a complete description
+of the available MIX binary instructions.
+
+@node MIX instruction set, , MIX architecture, The MIX computer
+@comment node-name, next, previous, up
+@subsection MIX instruction set
+@cindex instruction set
+
+The following subsections fully describe the instruction set of the MIX
+computer. We begin with a description of the structure of binary
+instructions and the notation used to refer to their subfields. The
+remaininig subsections are devoted to describing the actual instructions
+available to the MIX programmer.
+
+@menu
+* Instruction structure::
+* Loading operators::
+* Storing operators::
+* Arithmetic operators::
+* Address transfer operators::
+* Comparison operators::
+* Jump operators::
+* Input-output operators::
+* Conversion operators::
+* Shift operators::
+* Miscellaneous operators::
+* Execution times::
+@end menu
+
+@node Instruction structure, Loading operators, MIX instruction set, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Instruction structure
+
+MIX @dfn{instructions} are codified as words with the following subfield
+structure:
+
+@multitable @columnfractions .15 .20 .65
+@item @emph{Subfield} @tab @emph{fspec} @tab @emph{Description}
+@item ADDRESS @tab (0:2)
+@tab The first two bytes plus sign are the @dfn{address} field. Combined
+with the INDEX field, denotes the memory address to be used by the
+instruction.
+@item INDEX @tab (3:3)
+@tab The third byte is the @dfn{index}, normally used for indexing the
+address@footnote{The actual memory address the instruction refers to, is
+obtained by adding to ADDRESS the value of the @samp{rI} register
+denoted by INDEX.}.
+@item MOD @tab (4:4)
+@tab Byte four is used either as an operation code modifier or as a field
+specification.
+@item OPCODE @tab (5:5)
+@tab The last (least significant) byte in the word denotes the operation
+code.
+@end multitable
+
+@noindent
+or, graphically,
+
+@example
+ ------------------------------------------------
+| 0 | 1 | 2 | 3 | 4 | 5 |
+ ------------------------------------------------
+| ADDRESS | INDEX | MOD | OPCODE |
+ ------------------------------------------------
+@end example
+
+For a given instruction, @samp{M} stands for
+the memory address obtained after indexing the ADDRESS subfield
+(using its INDEX byte), and @samp{V} is the contents of the
+subfield indicated by MOD of the memory cell with address @samp{M}. For
+instance, suppose that we have the following contents of MIX registers
+and memory cells:
+
+@example
+[rI2] = + 00 63
+[31] = - 10 11 00 11 22
+@end example
+@noindent
+where @samp{[n]} denotes the contents of the nth memory cell and
+@samp{[rI2]} the contents of register @samp{rI2}@footnote{In general,
+@samp{[X]} will denote the contents of entity @samp{X}; thus, by
+definition, @w{@samp{V = [M](MOD)}}.}. Let us consider the binary
+instruction @w{@samp{I = - 00 32 02 11 10}}. For this instruction we
+have:
+
+@example
+ADDRESS = - 00 32 = -32
+INDEX = 02 = 2
+MOD = 11 = (1:3)
+OPCODE = 10
+
+M = ADDRESS + [rI2] = -32 + 63 = 31
+V = [M](MOD) = (- 10 11 00 11 22)(1:3) = + 00 00 10 11 00
+@end example
+
+In the following subsections, we will assing to each MIX instruction a
+mnemonic, or symbolic name. For instance, the mnemonic of @samp{OPCODE}
+10 is @samp{LD2}. Thus we can rewrite the above instruction as
+
+@example
+LD2 -32,2(1:3)
+@end example
+@noindent
+or, for a generic instruction:
+
+@example
+MNEMONIC ADDRESS,INDEX(MOD)
+@end example
+@noindent
+Some instructions are identified by both the OPCODE and the MOD
+fields. In these cases, the MOD will not appear in the above symbolic
+representation. Also when ADDRESS or INDEX are zero, they can be
+omitted. Finally, MOD defaults to (0:5) (meaning the
+whole word).
+
+@node Loading operators, Storing operators, Instruction structure, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Loading operators
+@cindex loading operators
+
+The following instructions are used to load memory contents into a
+register.
+
+@ftable @code
+@item LDA
+Put in rA the contents of cell no. M.
+OPCODE = 8, MOD = fspec. @code{rA <- V}.
+@item LDX
+Put in rX the contents of cell no. M.
+OPCODE = 15, MOD = fspec. @code{rX <- V}.
+@item LDi
+Put in rIi the contents of cell no. M.
+OPCODE = 8 + i, MOD = fspec. @code{rIi <- V}.
+@item LDAN
+Put in rA the negative contents of cell no. M.
+OPCODE = 16, MOD = fspec. @code{rA <- -V}.
+@item LDXN
+Put in rX the negative contents of cell no. M.
+OPCODE = 23, MOD = fspec. @code{rX <- -V}.
+@item LDiN
+Put in rIi the negative contents of cell no. M.
+OPCODE = 16 + i, MOD = fspec. @code{rIi <- -V}.
+@end ftable
+
+In all the above load instructions the @samp{MOD} field selects the
+bytes of the memory cell with address @samp{M} which are loaded into the
+requisite register (indicated by the @samp{OPCODE}). For instance, the
+word @w{@samp{+ 00 13 01 27 11}} represents the instruction
+
+@example
+LD3 13,1(3:3)
+ ^ ^ ^ ^
+ | | | |
+ | | | --- MOD = 27 = 3*8 + 7
+ | | --- INDEX = 1
+ | --- ADDRESS = 00 13
+ --- OPCODE = 11
+@end example
+Let us suppose that, prior to this instruction execution, the state of
+the MIX computer is the following:
+
+@example
+[rI1] = - 00 01
+[rI3] = + 24 12
+[12] = - 01 02 03 04 05
+@end example
+@noindent
+As, in this case, @w{@samp{M = 13 + [rI1] = 12}}, we have
+@w{@samp{V = [M](3:3) = (- 01 02 03 04 05)(3:3) = + 00 00 00 00 03}}
+(note that the specified subfield is left-padded with null bytes to
+complete a word). Hence, the MIX state, after the instruction execution,
+will be
+
+@example
+[rI1] = - 00 01
+[rI3] = + 00 03
+[12] = - 01 02 03 04 05
+@end example
+
+To further illustrate loading operators, the following table shows the
+contents of @samp{rX} after different @samp{LDX} instructions:
+
+@table @samp
+@item LDX 12(0:0) [rX] = - 00 00 00 00 00
+@item LDX 12(0:1) [rX] = - 00 00 00 00 01
+@item LDX 12(3:5) [rX] = + 00 00 03 04 05
+@item LDX 12(3:4) [rX] = + 00 00 00 03 04
+@item LDX 12(0:5) [rX] = - 01 02 03 04 05
+@end table
+
+
+@node Storing operators, Arithmetic operators, Loading operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Storing operators
+@cindex storing operators
+
+The following instructions are the inverse of the load
+operations: they are used to store a subfield of a register
+into a memory location. Here, MOD represents the subfield of the memory
+cell that is to be overwritten with bytes from a register. These bytes
+are taken beginning by the rightmost side of the register.
+
+@ftable @code
+@item STA
+Store rA. OPCODE = 24, MOD = fspec. @code{V <- rA}.
+@item STX
+Store rX. OPCODE = 31, MOD = fspec. @code{V <- rX}.
+@item STi
+Store rIi. OPCODE = 24 + i, MOD = fspec. @code{V <- rIi}.
+@item STJ
+Store rJ. OPCODE = 32, MOD = fspec. @code{V <- rJ}.
+@item STZ
+Store zero. OPCODE = 33, MOD = fspec. @code{V <- 0}.
+@end ftable
+
+By way of example, consider the instruction @samp{STA 1200(2:3)}. It
+causes the MIX to fetch bytes no. 4 and 5 of register A and copy them to
+bytes 2 and 3 of memory cell no. 1200 (remember that, for these
+instructions, MOD specifies a subfield of @emph{the memory
+address}). The others bytes of the memory cell retain their
+values. Thus, if prior to the instruction execution we have
+
+@example
+[1200] = - 20 21 22 23 24
+[rA] = + 01 02 03 04 05
+@end example
+@noindent
+we will end up with
+
+@example
+[1200] = - 20 04 05 23 24
+[rA] = + 01 02 03 04 05
+@end example
+
+As a second example, @samp{ST2 1000(0)} will set the sign of
+@samp{[1000]} to that of @samp{[rI2]}.
+
+@node Arithmetic operators, Address transfer operators, Storing operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Arithmetic operators
+@cindex arithmetic operators
+
+The following instructions perform arithmetic operations between rA and
+rX register and memory contents.
+
+@ftable @code
+@item ADD
+Add and set OV if overflow. OPCODE = 1, MOD = fspec.
+@w{@code{rA <- rA +V}}.
+@item SUB
+Sub and set OV if overflow. OPCODE = 2, MOD = fspec.
+@w{@code{rA <- rA - V}}.
+@item MUL
+Multiply V times rA and store the 10-bytes product in rAX.
+OPCODE = 3, MOD = fspec. @w{@code{rAX <- rA x V}}.
+@item DIV
+rAX is considered a 10-bytes number, and it is divided by V.
+OPCODE = 4, MOD = fspec. @w{@code{rA <- rAX / V}}, @code{rX} <- reminder.
+@end ftable
+
+In all the above instructions, @samp{[rA]} is one of the operands
+of the binary arithmetic operation, the other being @samp{V} (that is,
+the specified subfield of the memory cell with address @samp{M}), padded
+with zero bytes on its left-side to complete a word. In multiplication
+and division, the register @samp{X} comes into play as a right-extension
+of the register @samp{A}, so that we are able to handle 10-byte numbers
+whose more significant bytes are those of @samp{rA} (the sign of this
+10-byte number is that of @samp{rA}: @samp{rX}'s sign is ignored).
+
+Addition and substraction of MIX words can give rise to overflows, since
+the result is stored in a register with room to only 5 bytes (plus
+sign). When this occurs, the operation result modulo @w{1,073,741,823}
+(the maximum value storable in a MIX word) is stored in @samp{rA}, and
+the overflow toggle is set to TRUE.
+
+@node Address transfer operators, Comparison operators, Arithmetic operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Address transfer operators
+@cindex address transfer operators
+
+In these instructions, @samp{M} (the address of the instruction after
+indexing) is used as a number instead of as the address of a memory
+cell.
+
+@ftable @code
+@item ENTA
+Enter [rA]. OPCODE = 48, MOD = 2. @code{rA <- M}.
+@item ENTX
+Enter [rX]. OPCODE = 55, MOD = 2. @code{rX <- M}.
+@item ENTi
+Enter [rIi]. OPCODE = 48 + i, MOD = 2. @code{rIi <- M}.
+@item ENNA
+Enter negative [rA]. OPCODE = 48, MOD = 3. @code{rA <- -M}.
+@item ENNX
+Enter negative [rX]. OPCODE = 55, MOD = 3. @code{rX <- -M}.
+@item ENNi
+Enter negative [rIi]. OPCODE = 48 + i, MOD = 3. @code{rIi <- -M}.
+@item INCA
+Increase [rA]. OPCODE = 48, MOD = 0. @code{rA <- rA + M}.
+@item INCX
+Increase [rX]. OPCODE = 55, MOD = 0. @code{rX <- rX + M}.
+@item INCi
+Increase [rIi]. OPCODE = 48 + i, MOD = 0. @code{rIi <- rIi + M}.
+@item DECA
+Decrease [rA]. OPCODE = 48, MOD = 1. @code{rA <- rA - M}.
+@item DECX
+Decrease [rX]. OPCODE = 55, MOD = 0. @code{rX <- rX - M}.
+@item DECi
+Decrease [rIi]. OPCODE = 48 + i, MOD = 0. @code{rIi <- rIi - M}.
+@end ftable
+
+In the above instructions, the subfield @samp{ADDRESS} acts as an
+immediate (indexed) operand, and allow us to set directly the contents
+of the MIX registers without an indirection to the memory cells (in a
+real CPU this would mean that they are faster that the previously
+discussed instructions, whose operands are fetched from memory). So, if
+you want to store in @samp{rA} the value -2000 (- 00 00 00 31 16), you
+can use the binary instruction @w{+ 31 16 00 03 48}, or, symbolically,
+
+@example
+ENNA 2000
+@end example
+@noindent
+Used in conjuction with the store operations (@samp{STA}, @samp{STX},
+etc.), these instructions also allow you to set memory cells contents to
+concrete values.
+
+Note that in these address transfer operators, the @samp{MOD} field is
+not a subfield specificator, but serves to define (together with
+@samp{OPCODE}) the concrete operation to be performed.
+
+@node Comparison operators, Jump operators, Address transfer operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Comparison operators
+@cindex comparison operators
+
+So far, we have learned how to move values around between the MIX
+registers and its memory cells, and also how to perform arithmetic
+operations using these values. But, in order to write non-trivial
+programs, other functionalities are needed. One of the most common is
+the ability to compare two values, which, combined with jumps, will
+allow the execution of conditional statements.
+The following instructions compare the value of a register with @samp{V}, and
+set the @sc{cm} indicator to the result of the comparison (i.e. to
+@samp{E}, @samp{G} or @samp{L}, equal, greater or lesser respectively).
+
+@ftable @code
+@item CMPA
+Compare [rA] with V. OPCODE = 56, MOD = fspec.
+@item CMPX
+Compare [rX] with V. OPCODE = 63, MOD = fspec.
+@item CMPi
+Compare [rIi] with V. OPCODE = 56 + i, MOD = fspec.
+@end ftable
+
+As explained above, these instructions modify the value of the MIX
+comparison indicator; but maybe you are asking yourself how do you use
+this value: enter jump operators, in the next subsection.
+
+@node Jump operators, Input-output operators, Comparison operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Jump operators
+@cindex jump operators
+
+The MIX computer has an internal register, called the @dfn{location
+counter}, which stores the address of the next instruction to be fetched
+and executed by the virtual CPU. You cannot directly modify the contents
+of this internal register with a load instruction: after fetching the
+current instruction from memory, it is automatically increased in one
+unit by the MIX. However, the is a set of instructions (which we call
+jump instructions) which can alter the contents of the location counter
+provided some condition is met. When this occurs, the value of the next
+instruction address that would have been fetched in the absence of the
+jump is stored in @samp{rJ} (except for @code{JSJ}), and the location
+counter is set to the value of @samp{M} (so that the next instruction is
+fetched from this new address). Later on, you can return to the point
+when the jump occurred reading the address stored in @samp{rJ}.
+
+The MIX computer provides the following jump instructions:
+With these instructions you force a jump to the specified address. Use
+@samp{JSJ} if you do not care about the return address.
+
+@ftable @code
+@item JMP
+Unconditional jump. OPCODE = 39, MOD = 0.
+@item JSJ
+Unconditional jump, but rJ is not modified. OPCODE = 39, MOD = 1.
+@end ftable
+
+These instructions check the overflow toggle to decide whether to jump
+or not.
+
+@ftable @code
+@item JOV
+Jump if OV is set (and turn it off). OPCODE = 39, MOD = 2.
+@item JNOV
+Jump if OV is not set (and turn it off). OPCODE = 39, MOD = 3.
+@end ftable
+
+In the following instructions, the jump is conditioned to the contents of the
+comparison flag:
+
+@ftable @code
+@item JL
+Jump if @w{@code{[CM] = L}}. OPCODE = 39, MOD = 4.
+@itemx JE
+Jump if @w{@code{[CM] = E}}. OPCODE = 39, MOD = 5.
+@itemx JG
+Jump if @w{@code{[CM] = G}}. OPCODE = 39, MOD = 6.
+@itemx JGE
+Jump if @code{[CM]} does not equal @code{L}. OPCODE = 39, MOD = 7.
+@itemx JNE
+Jump if @code{[CM]} does not equal @code{E}. OPCODE = 39, MOD = 8.
+@itemx JLE
+Jump if @code{[CM]} does not equal @code{G}. OPCODE = 39, MOD = 9.
+@end ftable
+
+You can also jump conditioned to the value stored in the MIX registers,
+using the following instructions:
+
+@ftable @code
+@item JAN
+@itemx JAZ
+@itemx JAP
+@itemx JANN
+@itemx JANZ
+@itemx JANP
+Jump if the contents of rA is, respectively, negative, zero, positive,
+non-negative, non-zero or non-positive.
+OPCODE = 40, MOD = 0, 1, 2, 3, 4, 5.
+@item JXN
+@itemx JXZ
+@itemx JXP
+@itemx JXNN
+@itemx JXNZ
+@itemx JXNP
+Jump if the contents of rX is, respectively, negative, zero, positive,
+non-negative, non-zero or non-positive.
+OPCODE = 47, MOD = 0, 1, 2, 3, 4, 5.
+@item JiN
+@itemx JiZ
+@itemx JiP
+@itemx JiNN
+@itemx JiNZ
+@itemx JiNP
+Jump if the contents of rIi is, respectively, negative, zero, positive,
+non-negative, non-zero or non-positive.
+OPCODE = 40 + i, MOD = 0, 1, 2, 3, 4, 5.
+@end ftable
+
+
+@node Input-output operators, Conversion operators, Jump operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Input-output operators
+@cindex input-output operators
+
+As explained in previous sections (@pxref{MIX architecture}), the MIX
+computer can interact with a series of block devices. To that end, you
+have at your disposal the following instructions:
+
+@ftable @code
+@item IN
+Transfer a block of words from the specified unit to memory, starting at
+address M.
+OPCODE = 36, MOD = I/O unit.
+@item OUT
+Transfer a block of words from memory (starting at address M) to the
+specified unit.
+OPCODE = 37, MOD = I/O unit.
+@item IOC
+Perfom a control operation (given by M) on the specified unit.
+OPCODE = 35, MOD = I/O unit.
+@item JRED
+Jump to M if the specified unit is ready.
+OPCODE = 38, MOD = I/O unit.
+@item JBUS
+Jump to M if the specified unit is busy.
+OPCODE = 34, MOD = I/O unit.
+@end ftable
+@noindent
+In all the above instructions, the @samp{MOD} subfile must be in the
+range 0-20, since it denotes the operation's target device. The
+@samp{IOC} instruction only makes sense for tape devices (@samp{MOD} =
+0-7 or 20): it shifts the read/write pointer by the number of words
+given by @samp{M} (if it equals zero, the tape is rewound)@footnote{In
+Knuth's original definition, there are other control operations
+available, but they do not make sense when implementing the block
+devices as disk files (as we do in @sc{mdk} simulator). For the same
+reason, @sc{mdk} devices are always ready, since all input-output
+operations are performed using synchronous system calls.}.
+
+
+@node Conversion operators, Shift operators, Input-output operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Conversion operators
+@cindex conversion operators
+
+The following instructions convert between numerical values and their
+character representations.
+
+@ftable @code
+@item NUM
+Convert rAX, assumed to contain a character representation of a number,
+to its numerical value and store it in rA.
+OPCODE = 5, MOD = 0.
+@item CHAR
+Convert the number stored in rA to a character representation and store
+it in rAX.
+OPCODE = 5, MOD = 1.
+@end ftable
+@noindent
+Digits are represented in MIX by the range of values 30-39 (digits
+9-0). Thus, if the contents of @samp{rA} and @samp{rX} is, for instance,
+
+@example
+[rA] = + 30 30 31 32 33
+[rX] = + 31 35 39 30 34
+@end example
+@noindent
+the represented number is 0012315904, and @samp{NUM} will store this
+value in @samp{rA} (i.e., we end up with @samp{[rA]} = @w{+ 0 46 62 52
+0} = 12315904. @samp{CHAR} performs the inverse operation.
+
+@node Shift operators, Miscellaneous operators, Conversion operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Shift operators
+@cindex shift
+@cindex shift operators
+
+The following instructions perform byte-wise shifts of the contents of
+@samp{rA} and @samp{rX}.
+
+@ftable @code
+@item SLA
+@itemx SRA
+@itemx SLAX
+@itemx SRAX
+@itemx SLC
+@itemx SRC
+Shift rA or rAX left, right, or rAX circularly left or right. M
+specifies the number of bytes to be shifted.
+OPCODE = 6, MOD = 0, 1, 2, 3, 4, 5.
+@end ftable
+@noindent
+If we begin with, say, @samp{[rA]} = @w{- 01 02 03 04 05}, we would
+have the following modifications to @samp{rA} contents when performing
+the instructions on the left column:
+
+@multitable {SLA 00} {[rA] = - 00 00 00 00 00}
+@item SLA 2 @tab [rA] = - 03 04 05 00 00
+@item SRA 1 @tab [rA] = - 00 01 02 03 04
+@item SLC 3 @tab [rA] = - 04 05 01 02 03
+@item SRC 24 @tab [rA] = - 05 01 02 03 04
+@end multitable
+@noindent
+Note that the sign is unaffected by shift operations. On the other hand,
+@samp{SLAX} and @samp{SRAX} treat @samp{rA} and @samp{rX} as a single
+10-bytes register (ignoring again the signs), so that, if we begin with
+@samp{[rA]} = @w{+ 01 02 03 04 05} and @samp{[rX]} = @w{- 06 07 08 09
+10}, executing @samp{SLAX 3} would yield:
+
+@example
+[rA] = + 04 05 06 07 08 [rX] = - 09 10 00 00 00
+@end example
+
+@node Miscellaneous operators, Execution times, Shift operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Miscellaneous operators
+@cindex miscellaneous operators
+
+Finally, we list in the following table three miscellaneous MIX
+instructions which do not fit in any of the previous subsections:
+
+@ftable @code
+@item MOVE
+Move MOD words from M to the location stored in rI1.
+OPCODE = 7, MOD = no. of bytes.
+@item NOP
+No operation. OPCODE = 0, MOD = 0.
+@item HLT
+Halt. Stops instruction fetching. OPCODE = 5, MOD = 2.
+@end ftable
+@noindent
+The only effect of executing @samp{NOP} is increasing the location
+counter, while @samp{HLT} usually marks program termination.
+
+@node Execution times, , Miscellaneous operators, MIX instruction set
+@comment node-name, next, previous, up
+@subsubsection Execution times
+
+@cindex exection time
+@cindex time
+
+When writing MIXAL programs (or any kind of programs, for that matter),
+whe shall often be interested in their execution time. Loosely speaking,
+we will interested in the answer to the question: how long takes a
+program to execute? Of course, this execution time will be a function of
+the input size, and the answer to our question is commonly given as the
+asymptotic behaviour as a function of the input size. At any rate, to
+compute this asymptotic behaviour, we need a measure of how long
+execution of a single instruction takes in our (virtual) CPU. Therefore,
+each MIX instruction will have an associated execution time, given in
+arbitrary units (in a real computer, the value of this unit will depend
+on the hardware configuration). When our MIX virtual machine executes
+programs, it will give you the value of their execution time based upon
+the execution time of each single instruction.
+
+In the following table, the execution times (in the above mentioned
+arbitrary units) of the MIX instructions are given.
+
+@multitable {INSSSS} {01} {INSSSS} {01} {INSSSS} {01} {INSSSS} {01}
+@item @code{NOP} @tab 1 @tab @code{ADD} @tab 2 @tab @code{SUB}
+@tab 2 @tab @code{MUL} @tab 10
+@item @code{DIV} @tab 12 @tab @code{NUM} @tab 10 @tab @code{CHAR}
+@tab 10 @tab @code{HLT} @tab 10
+@item @code{SLx} @tab 2 @tab @code{SRx} @tab 2 @tab @code{LDx}
+@tab 2 @tab @code{STx} @tab 2
+@item @code{JBUS} @tab 1 @tab @code{IOC} @tab 1 @tab @code{IN}
+@tab 1@tab @code{OUT} @tab 1
+@item @code{JRED} @tab 1 @tab @code{Jx} @tab 1 @tab @code{INCx}
+@tab 1 @tab @code{DECx} @tab 1
+@item @code{ENTx} @tab 1 @tab @code{ENNx} @tab 1 @tab @code{CMPx}
+@tab 1 @tab @code{MOVE} @tab 1+F
+@end multitable
+
+In the above table, 'F' stands for the number of blocks to be moved
+(given by the @code{FSPEC} subfield of the instruction); @code{SLx} and
+@code{SRx} are a short cut for the byte-shifting operations; @code{LDx}
+denote all the loading operations; @code{STx} are the storing
+operations; @code{Jx} stands for all the jump operations, and so on with
+the rest of abbreviations.
+
+@node MIXAL, , The MIX computer, MIX and MIXAL tutorial
+@comment node-name, next, previous, up
+@section MIXAL
+@cindex MIXAL
+@cindex MIX assembly language
+@cindex assembly
+
+In the previous sections we have listed all the available MIX binary
+instructions. As we have shown, each instruction is represented by a
+word which is fetched from memory and executed by the MIX virtual
+CPU. As is the case with real computers, the MIX knows how to decode
+instructions in binary format (the so--called machine language), but a
+human programmer would have a tough time if she were to write her
+programs in machine language. Fortunately, the MIX computer can be
+programmed using an assembly language, MIXAL, which provides a symbolic
+way of writing the binary instructions understood by the imaginary MIX
+computer. If you have used assembler languages before, you will find
+MIXAL a very familiar language. MIXAL source files are translated
+to machine language by a MIX assembler, which produces a binary file (the
+actual MIX program) which can be directly loaded into the MIX memory and
+subsequently executed.
+
+In this section, we describe MIXAL, the MIX assembly language. The
+implementation of the MIX assembler program and MIX computer simulator
+provided by @sc{mdk} are described later on (@pxref{Getting started}).
+
+@menu
+* Basic structure:: Writing basic MIXAL programs.
+* MIXAL directives:: Assembler directives.
+* Expressions:: Evaluation of expressions.
+* W-expressions:: Evaluation of w-expressions.
+* Local symbols:: Special symbol table entries.
+* Literal constants:: Specifying an immediate operand.
+@end menu
+
+@node Basic structure, MIXAL directives, MIXAL, MIXAL
+@comment node-name, next, previous, up
+@subsection Basic program structure
+
+The MIX assembler reads MIXAL files line by line, producing, when
+required, a binary instruction, which is associated to a predefined
+memory address. To keep track of the current address, the assembler
+maintains an internal location counter which is incremented each time an
+instruction is compiled. In addition to MIX instructions, you can
+include in MIXAL file assembly directives (or pseudoinstructions)
+addressed at the assembler itself (for instance, telling it where the
+program starts and ends, or to reposition the location counter; see below).
+
+MIX instructions and assembler directives@footnote{We shall call them,
+collectively, MIXAL instructions.} are written in MIXAL (one per
+source file line) according to the following pattern:
+
+@example
+[LABEL] MNEMONIC [OPERAND] [COMMENT]
+@end example
+
+@noindent
+where @samp{OPERAND} is of the form
+
+@example
+[ADDRESS][,INDEX][(MOD)]
+@end example
+
+Items between square brackets are optional, and
+
+@table @code
+@item LABEL
+Is an alphanumeric identifier (a @dfn{symbol}) which gets the current
+value of the location counter, and can be used in subsequent
+expressions.
+@item MNEMONIC
+Is a literal denoting the operation code of the instruction
+(e.g. @code{LDA}, @code{STA}; see @pxref{MIX instruction set}) or an
+assembly pseudoinstruction (e.g. @code{ORG}, @code{EQU}).
+@item ADDRESS
+Expression evaluating to the address subfield of the instruction.
+@item INDEX
+Expression evaluating to the index subfield of the instruction. It
+defaults to 0 (i.e., no use of indexing) and can only be used when
+@code{ADDRESS} is present.
+@item MOD
+Expression evaluating to the mod subfield of the instruction. Its
+default value, when omitted, depends on @code{OPCODE}.
+@item COMMENT
+Any number of spaces after the operand mark the beggining of a comment,
+i.e. any text separated by white space from the operand is ignored by
+the assembler (note that spaces are not allowed within the
+@samp{OPERAND} field).
+@end table
+
+Note that spaces are @emph{not} allowed between the @code{ADDRESS},
+@code{INDEX} and @code{MOD} fields if they are present. White space is
+used to separate the label, operation code and operand parts of the
+instruction@footnote{In fact, Knuth's definition of MIXAL restricts the
+column number at which each of these instruction parts must start. The
+MIXAL assembler included in @sc{mdk}, @code{mixasm}, does not impose
+such restriction.}.
+
+We have already listed the mnemonics associated will each MIX
+instructions; sample MIXAL instructions representing MIX instructions
+are:
+@example
+HERE LDA 2000 HERE represents the current location counter
+ LDX HERE,2(1:3) this is a comment
+ JMP 1234
+@end example
+
+@node MIXAL directives, Expressions, Basic structure, MIXAL
+@comment node-name, next, previous, up
+@subsection MIXAL directives
+
+MIXAL instructions can be either one of the MIX machine instructions
+(@pxref{MIX instruction set}) or one of the following assembly
+pseudoinstructions:
+
+@ftable @code
+@item ORIG
+Sets the value of the memory address to which following instructions
+will be allocated after compilation.
+@item EQU
+Used to define a symbol's value, e.g. @w{@code{SYM EQU 2*200/3}}.
+@item CON
+The value of the given expression is copied directly into the current
+memory address.
+@item ALF
+Takes as operand five characters, constituting the five bytes of a word
+which is copied directly into the current memory address.
+@item END
+Marks the end of the program. Its operand gives the start address for
+program execution.
+@end ftable
+
+The operand of @code{ORIG}, @code{EQU}, @code{CON} and @code{END} can be
+any expression evaluating to a constant MIX word, i.e., either a simple
+MIXAL expression (composed of numbers, symbols and binary operators,
+@pxref{Expressions}) or a w-expression (@pxref{W-expressions}).
+
+All MIXAL programs must contain an @code{END} directive, with a twofold
+end: first, it marks the end of the assembler job, and, in the second
+place, its (mandatory) operand indicates the start address for the
+compiled program (that is, the address at which the virtual MIX machine
+must begin fetching instructions after loading the program). It is also
+very common (although not mandatory) to include at least an @code{ORIG}
+directive to mark the initial value of the assembler's location counter
+(remember that it stores the address associated with each compiled MIX
+instruction). Thus, a minimal MIXAL program would be
+
+@example
+ ORIG 2000 set the initial compilation adress
+ NOP this instruction will be loaded at adress 2000
+ HLT and this one at address 2001
+ END 2000 end of program; execution will start at address 2000
+this line is not parsed by the assembler
+@end example
+@noindent
+The assembler will generate two binary instructions (@code{NOP} (@w{+ 00
+00 00 00 00}) and @code{HLT} (+ 00 00 02 05)), which will be loaded at
+addresses 2000 and 2001. Execution of the program will begin at address
+2000. Every MIXAL program should also include a @code{HLT} instruction,
+which will mark the end of program execution (but not of program
+compilation).
+
+The @code{EQU} directive allows the definition of symbolic names for
+specific values. For instance, we could rewrite the above program as
+follows:
+
+@example
+START EQU 2000
+ ORIG START
+ NOP
+ HLT
+ END START
+@end example
+@noindent
+which would give rise to the same compiled code. Symbolic constants (or
+symbols, for short) can also be implicitly defined placing them in the
+@code{LABEL} field of a MIXAL instruction: in this case, the assembler
+assigns to the symbol the value of the location counter before compiling
+the line. Hence, a third way of writing our trivial program is
+
+@example
+ ORIG 2000
+START NOP
+ HLT
+ END START
+@end example
+
+The @code{CON} directive allows you to directly specify the contents of
+the memory address pointed by the location counter. For instance, when
+the assembler encounters the following code snippet
+
+@example
+ ORIG 1150
+ CON -1823473
+@end example
+@noindent
+it will assign to the memory cell number 1150 the contents @w{- 00 06 61
+11 49} (which corresponds to the decimal value -1823473).
+
+Finally, the @code{ALF} directive let's you specify the memory contents
+as a set of five (quoted) characters, which are translated by the
+assembler to their byte values, conforming in that way the binary word
+that is to be stored in the corresponding memory cell. This directive
+comes in handy when you need to store printable messages in a memory
+address, as in the following example:
+
+@example
+ OUT MSG MSG is not yet defined here (future reference)
+MSG ALF "THIS " MSG gets defined here
+ ALF "IS A "
+ ALF "MESSA"
+ ALF "GE. "
+@end example
+@noindent
+The above snippet also shows the use of a @dfn{future reference}, that
+is, the usage of a symbol (@code{MSG} in the example) prior of its actual
+definition. The MIXAL assembler is able to handle future references
+subject to some limitations which are described in the following section
+(@pxref{Expressions}).
+
+@cindex comments
+
+Any line starting with an asterisk is treated as a comment and ignored
+by the assembler.
+
+@example
+* This is a comment: this line is ignored.
+ * This line is an error: * must be in column 1.
+@end example
+
+As noted in the previous section, comments can also be located after the
+@code{MNEMONIC} field of an instruction, separated from it by white
+space, as in
+
+@example
+LABEL LDA 100 This is also a comment
+@end example
+
+@node Expressions, W-expressions, MIXAL directives, MIXAL
+@comment node-name, next, previous, up
+@subsection Expressions
+@cindex operator
+@cindex binary operator
+@cindex unary operator
+The @code{ADDRESS}, @code{INDEX} and @code{MOD} fields of a MIXAL
+instruction can be expressions, formed by numbers, identifiers and
+binary operators (@code{+ - * / // :}). @code{+} and @code{-} can also
+be used as unary operators. Order of evaluation is from left to right:
+there is no other operator precedence rule, and parentheses cannot be
+used for grouping. A stand-alone asterisk denotes the current memory
+location; thus, for instance,
+
+@example
+ 4+2**
+@end example
+
+@noindent
+evaluates to 4 plus two times the current memory location. White space
+is not allowed within expressions.
+
+The special binary operator @code{:} has the same meaning as in fspecs,
+i.e.,
+
+@example
+A:B = 8*A + B
+@end example
+@noindent
+while @code{A//B} stands for the quotient of the ten-byte number @w{@code{A} 00
+00 00 00 00} (that is, A right-padded with 5 null bytes or, what amounts
+to the same, multiplied by 64 to the fifth power) divided by
+@code{B}. Sample expressions are:
+
+@example
+18-8*3 = 30
+14/3 = 4
+1+3:11 = 4:11 = 43
+1//64 = (01 00 00 00 00 00)/(00 00 00 01 00) = (01 00 00 00 00 00)
+@end example
+@noindent
+Note that all MIXAL expressions evaluate to a MIX word (by definition).
+
+All symbols appearing within an expression must be previously defined. Future
+references are only allowed when appearing stand-alone (or modified by
+an unary operator) in the @code{ADDRESS} part of a MIXAL instruction,
+e.g.
+
+@example
+* OK: stand alone future reference
+ STA -S1(1:5)
+* ERROR: future reference in expression
+ LDX 2-S1
+S1 LD1 2000
+@end example
+
+@node W-expressions, Local symbols, Expressions, MIXAL
+@comment node-name, next, previous, up
+@subsection W-expressions
+@cindex w-expressions
+
+Besides expressions, as described above (@pxref{Expressions}), the MIXAL
+assembler is able to handle the so called @dfn{w-expressions} as the
+operands of the directives @code{ORIG}, @code{EQU}, @code{CON} and
+@code{END} (@pxref{MIXAL directives}). The general form of a
+w-expression is the following:
+
+@example
+ WEXP = EXP[(EXP)][,WEXP]
+@end example
+@noindent
+where @code{EXP} stands for an expression and square brackets denote
+optional items. Thus, a w-expression is made by a regular expression
+followed by an optional expression between parenthesis, followed by any
+number of similar constructs separated by commas. Sample w-expressions
+are:
+
+@example
+2000
+235(3)
+S1+3(S2),3000
+S1,S2(3:5),23
+@end example
+
+W-expressions are evaluated as follows. First, all expressions are
+evaluated according to the rules given in the previous section. Thus, if
+we start with, say, @samp{S1+2(2:4)} where @samp{S1} equals 265230, we
+have @samp{265232(2:4)}. The expression between parenthesis must be a
+valid f-spec, for it specifies the bytes to be taken from the preceding
+word. In our example, we must take 3 bytes of the word @w{@samp{+ 00 01
+00 48 16}} (which is 265232), and store them in positions 2, 3 and 4 of
+the result, resulting in the new word @w{@samp{+ 00 00 48 16 00}} (i.e.,
+the decimal value 197632). When we have two expressions separated with a
+comma, we take, for each one, the subfield specified and compose the
+word to obtain the result. For instance, in the w-expression
+
+@example
+1(1:2),66(4:5)
+@end example
+@noindent
+we first take two bytes from 1 (00 and 01) and store them as bytes 1 and
+2 of the result (obtaining @w{@samp{+ 00 01 00 00 00}}) and, afterwards,
+take two bytes from 66 (01 and 02) and store them as bytes 4 and 5 of
+the result, obtaining @w{@samp{+ 00 01 00 01 02}} (262210). The process
+is repeated for each new comma-separated example. For instance:
+
+@example
+1(1:1),2(2:2),3(3:3),4(4:4) = 01 02 03 04 00
+@end example
+
+As stated before, w-expressions can only appear as the operands of MIXAL
+directives taking a constant value (@code{ORIG}, @code{EQU}, @code{CON}
+and @code{END}). Future references are @emph{not} allowed within
+w-expressions (i.e., all symbols appearing in a w-expression must be
+defined before they are used).
+
+@node Local symbols, Literal constants, W-expressions, MIXAL
+@comment node-name, next, previous, up
+@subsection Local symbols
+@cindex local symbols
+
+Besides user defined symbols, MIXAL programmers can use the so called
+@dfn{local symbols}, which are symbols of the form @code{[1-9][HBF]}. A
+local symbol @code{nB} refers to the address of the last previous
+occurrence of @code{nH} as a label, while @code{nF} refers to the next
+@code{nH} occurrence. Unlike user defined symbols, @code{nH} can appear
+multiple times in the @code{LABEL} part of different MIXAL
+instructions. The following code shows an instance of local symbols'
+usage:
+
+@example
+* line 1
+1H LDA 100
+* line 2: 1B refers to address of line 1, 3F refers to address of line 4
+ STA 3F,2(1B//2)
+* line 3: redefinition of 1H
+1H STZ
+* line 4: 1B refers to address of line 3
+3H JMP 1B
+@end example
+
+Note that a @code{B} local symbol never refers to a definition in its
+own line, that is, in the following program:
+
+@example
+ ORIG 1999
+ST NOP
+3H EQU 69
+3H ENTA 3B local symbol 3B refers to 3H in previous line
+ HLT
+ END ST
+@end example
+@noindent
+the contents of @samp{rA} is set to 69 and @emph{not} to 2001. An
+specially tricky case occurs when using local symbols in conjunction
+with @code{ORIG} pseudoinstructions. To wit@footnote{The author wants to
+thank Philip E. King for pointing these two special cases of local
+symbol usage to him.},
+
+@example
+ ORIG 1999
+ST NOP
+3H CON 10
+ ENT1 *
+ LDA 3B
+** rI1 is 2001, rA is 10. So far so good!
+3H ORIG 3B+1000
+** at this point 3H equals 2003
+** and the location counter equals 3000.
+ ENT2 *
+ LDX 3B
+** rI2 contains 3000, rX contains 2003.
+ HLT
+ END ST
+@end example
+
+@node Literal constants, , Local symbols, MIXAL
+@comment node-name, next, previous, up
+@subsection Literal constants
+@cindex literal constants
+
+MIXAL allows the introduction of @dfn{literal constants}, which are
+automatically stored in memory addresses after the end of the program by
+the assembler. Literal constants are denoted as @code{=wexp=}, where
+@code{exp} is an w-expression (@pxref{W-expressions}). For instance, the
+code
+
+@example
+L EQU 10
+ LDA =20-L=
+@end example
+
+causes the assembler to add after the program's end an instruction with
+contents 10, and to assemble the above code as the instruction @w{@code{
+LDA a}}, where @code{a} stands for the address in which the value 10 is
+stored. In other words, the compiled code is equivalent to the
+following:
+
+@example
+L EQU 10
+ LDA a
+@dots{}
+a CON 20-L
+ END start
+@end example
+
diff --git a/doc/ss_devices.png b/doc/ss_devices.png
new file mode 100644
index 0000000..bb2ee83
--- /dev/null
+++ b/doc/ss_devices.png
Binary files differ
diff --git a/doc/ss_mix.png b/doc/ss_mix.png
new file mode 100644
index 0000000..9d0e6b6
--- /dev/null
+++ b/doc/ss_mix.png
Binary files differ
diff --git a/doc/ss_mix.txt b/doc/ss_mix.txt
new file mode 100644
index 0000000..757026e
--- /dev/null
+++ b/doc/ss_mix.txt
@@ -0,0 +1,31 @@
+|-----------------------------------------------------------|
+| Menu |
+|-----------------------------------------------------------|
+| |
+| |
+| |
+| |
+| MIXVM / MIXAL / Devices |
+| |
+| |
+| |
+| |
+| |
+| |
+|-----------------------------------------------------------|
+| |
+| Command output |
+| |
+| |
+| |
+|-----------------------------------------------------------|
+| Command prompt |
+|-----------------------------------------------------------|
+| Status bar |
+|-----------------------------------------------------------|
+
+
+
+
+
+
diff --git a/doc/ss_mixal.png b/doc/ss_mixal.png
new file mode 100644
index 0000000..506a170
--- /dev/null
+++ b/doc/ss_mixal.png
Binary files differ
diff --git a/doc/ss_worddlg.png b/doc/ss_worddlg.png
new file mode 100644
index 0000000..be6e7f2
--- /dev/null
+++ b/doc/ss_worddlg.png
Binary files differ
diff --git a/misc/.cvsignore b/misc/.cvsignore
new file mode 100644
index 0000000..282522d
--- /dev/null
+++ b/misc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/misc/Makefile.am b/misc/Makefile.am
new file mode 100644
index 0000000..bf21fc6
--- /dev/null
+++ b/misc/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2001 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+EXTRA_DIST = mixvm.el
+
diff --git a/misc/mixvm.el b/misc/mixvm.el
new file mode 100644
index 0000000..71e1fb5
--- /dev/null
+++ b/misc/mixvm.el
@@ -0,0 +1,157 @@
+;;; mixvm.el --- mdk's mixvm / Emacs gud interaction
+;; Copyright (C) 2001 Free Software Foundation, Inc.
+
+;; Author: Philip Ellis King <pking@pdq.net>
+;; Maintainer: Philip Ellis King <pking@pdq.net>
+;; Created: 12 Feb 2001
+;; Version: 0.2
+;; Keywords: tools
+
+
+;;; Commentary:
+;; mixvm.el provides an interface between mdk's mixvm and Emacs,
+;; via gud. Place this file in your load-path, optionally adding
+;; the following line to your .emacs file:
+;; (autoload 'mixvm "mixvm" "mixvm/gud interaction" t)
+;; Initiate a mdk/gud session with the command mixvm, gud will
+;; reflect the current line in the source file buffer.
+
+;; (mixvm.el is based on a study of gdb, perldb, and pdb as found
+;; in gud.el, and rubydb3x.el distributed with the source code to
+;; the Ruby language.
+
+;;; Change Log:
+;; Version 0.2
+;; Initial release
+
+
+;;; Code:
+(require 'gud)
+(provide 'mixvm)
+
+;;; History of argument lists passed to mixvm.
+(defvar gud-mixvm-history nil)
+
+;; rubydb3x provided good examples of xemacs/emacs
+;; compatibility (not interested at the moment)
+(defun gud-mixvm-massage-args (file args)
+ (cons "--emacs" args))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-mixvm-marker-acc "")
+(make-variable-buffer-local 'gud-mixvm-marker-acc)
+
+(defun gud-mixvm-marker-filter (string)
+ (setq gud-mixvm-marker-acc (concat gud-mixvm-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "\032\032mixvm:\\([^:]+\\):\\([0-9]+\\)"
+ gud-mixvm-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-mixvm-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-mixvm-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-mixvm-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-mixvm-marker-acc (substring gud-mixvm-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-mixvm-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ ;; (note: \\' matches the end of the string (Perl's '$'))
+ (if (string-match "\032.*\\'" gud-mixvm-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-mixvm-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-mixvm-marker-acc
+ (substring gud-mixvm-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-mixvm-marker-acc)
+ gud-mixvm-marker-acc ""))
+
+ output))
+
+;; See gdb for more comprehensive example
+;; pek: it bugs me that this is run for EVERY interactive
+;; mixvm command, should we cache some info somewhere?
+(defun gud-mixvm-find-file (file)
+ (save-excursion
+ (let* ((buf (find-file-noselect file)))
+ (set-buffer buf)
+ (gud-make-debug-menu)
+ buf)))
+
+
+(defvar mixvm-minibuffer-local-map nil
+ "Keymap for minibuffer prompting of mixvm startup command.")
+(if mixvm-minibuffer-local-map
+ ()
+ (setq mixvm-minibuffer-local-map (copy-keymap minibuffer-local-map))
+ (define-key
+ mixvm-minibuffer-local-map "\C-i" 'comint-dynamic-complete-filename))
+
+
+(defcustom gud-mixvm-command-name "mixvm"
+ "File name for executing the mixvm debugger.
+This should be an executable on your path, or an absolute file name."
+ :type 'string
+ :group 'gud)
+
+
+;;;###autoload
+(defun mixvm (command-line)
+ "Run mixvm on program FILE in buffer `*gud-FILE*'.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run mixvm (like this): "
+ (if (consp gud-mixvm-history)
+ (car gud-mixvm-history)
+ (concat gud-mixvm-command-name " "))
+ mixvm-minibuffer-local-map nil
+ '(gud-mixvm-history . 1))))
+
+ (gud-common-init command-line 'gud-mixvm-massage-args
+ 'gud-mixvm-marker-filter 'gud-mixvm-find-file)
+
+ (gud-def gud-break "sbp %l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-remove "cbp %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "next" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "next" "\C-n" "Step one line.")
+ (gud-def gud-stepi "next" "\C-i" "Step one line.")
+ (gud-def gud-cont "run" "\C-r" "Continue with display.")
+ (gud-def gud-finish "run" "\C-f" "Finish executing current function.")
+ (gud-def gud-print "weval %e" "\C-p" "Evaluate expression at point.")
+; (gud-def gud-up "up" "<" "Up one stack frame.")
+; (gud-def gud-down "down" ">" "Down one stack frame.")
+; ;; Is this right?
+; (gud-def gud-statement "! %e" "\C-e" "Execute Python statement at point.")
+
+; (local-set-key [menu-bar debug finish] '("Finish Function" . gud-finish))
+; (local-set-key [menu-bar debug up] '("Up Stack" . gud-up))
+; (local-set-key [menu-bar debug down] '("Down Stack" . gud-down))
+ (setq comint-prompt-regexp "^MIX > ")
+ (set (make-local-variable 'paragraph-start) comint-prompt-regexp)
+ (run-hooks 'mixvm-mode-hook))
+
+;;; mixvm.el ends here
diff --git a/mixgtk/.cvsignore b/mixgtk/.cvsignore
new file mode 100644
index 0000000..12ed8c2
--- /dev/null
+++ b/mixgtk/.cvsignore
@@ -0,0 +1,7 @@
+.deps
+Makefile
+Makefile.in
+gmixvm
+hello.mix
+mixgtk
+paper.dev
diff --git a/mixgtk/Makefile.am b/mixgtk/Makefile.am
new file mode 100644
index 0000000..f8b1bcf
--- /dev/null
+++ b/mixgtk/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2001 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+EXTRA_DIST = mixgtk.glade
+INCLUDES = -I$(includedir) -DGLADE_FILE=\""$(pkgdatadir)/mixgtk.glade"\"\
+ -DLOCAL_GLADE_FILE=\"mixgtk.glade\"
+LDADD = $(top_builddir)/mixlib/libmix.a
+
+if MAKE_GUI
+pkgdata_DATA = mixgtk.glade
+bin_PROGRAMS = gmixvm
+gmixvm_SOURCES = mixgtk.c mixgtk_gen_handlers.h mixgtk_gen_handlers.c \
+ mixgtk_cmd_dispatcher.h mixgtk_cmd_dispatcher.c \
+ mixgtk_widgets.h mixgtk_widgets.c \
+ mixgtk_device.h mixgtk_device.c \
+ mixgtk_mixvm.h mixgtk_mixvm.c \
+ mixgtk_mixal.h mixgtk_mixal.c \
+ mixgtk_input.h mixgtk_input.c
+endif
+
+
+
diff --git a/mixgtk/mixgtk.c b/mixgtk/mixgtk.c
new file mode 100644
index 0000000..1bbc175
--- /dev/null
+++ b/mixgtk/mixgtk.c
@@ -0,0 +1,91 @@
+/* -*-c-*- -------------- mixgtk.c :
+ * Main function of the mix gtk front-end
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/14 23:08:50 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <mixlib/mix.h>
+#include "mixgtk_widgets.h"
+#include "mixgtk_cmd_dispatcher.h"
+#include "mixgtk_device.h"
+#include "mixgtk_mixvm.h"
+#include "mixgtk_mixal.h"
+#include "mixgtk_input.h"
+
+int
+main(int argc, char *argv[])
+{
+ mix_vm_t *vm;
+
+ gtk_init(&argc, &argv);
+
+ mix_init_lib ();
+
+ if (!mixgtk_widget_factory_init (GLADE_FILE)
+ && !mixgtk_widget_factory_init (LOCAL_GLADE_FILE))
+ {
+ g_error ("Unable to initialise application (using %s and %s)\n",
+ GLADE_FILE, LOCAL_GLADE_FILE);
+ return EXIT_FAILURE;
+ }
+
+ if (!mixgtk_cmd_dispatcher_init ())
+ {
+ g_error ("Unable to initialise application (command dispatcher)\n");
+ return EXIT_FAILURE;
+ }
+
+ vm = mixgtk_cmd_dispatcher_get_vm ();
+
+ if (!mixgtk_device_init (GTK_NOTEBOOK
+ (mixgtk_widget_factory_get (MIXGTK_WIDGET_DEVICE)),
+ vm))
+ {
+ g_error ("Unable to initialise application (devices)\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!mixgtk_mixvm_init (vm))
+ {
+ g_error ("Unable to initialise application (mixvm widgets)\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!mixgtk_mixal_init (vm))
+ {
+ g_error ("Unable to initialise application (mixal widgets)\n");
+ return EXIT_FAILURE;
+ }
+
+ if (!mixgtk_input_init ())
+ {
+ g_error ("Unable to initialise application (word input widgets)\n");
+ return EXIT_FAILURE;
+ }
+
+
+ gtk_main();
+
+ mix_release_lib ();
+
+ return EXIT_SUCCESS;
+}
diff --git a/mixgtk/mixgtk.glade b/mixgtk/mixgtk.glade
new file mode 100644
index 0000000..ced029b
--- /dev/null
+++ b/mixgtk/mixgtk.glade
@@ -0,0 +1,1703 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>mixgtk</name>
+ <program_name>mixgtk</program_name>
+ <directory></directory>
+ <source_directory>src</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>False</gnome_support>
+ <gettext_support>False</gettext_support>
+ <use_widget_names>True</use_widget_names>
+ <output_build_files>False</output_build_files>
+ <backup_source_files>False</backup_source_files>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>main_window</name>
+ <signal>
+ <name>destroy</name>
+ <handler>on_main_window_destroy</handler>
+ <last_modification_time>Tue, 20 Feb 2001 21:58:29 GMT</last_modification_time>
+ </signal>
+ <title>gmixvm</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <default_width>650</default_width>
+ <default_height>500</default_height>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>True</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>main_vbox</name>
+ <border_width>2</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>2</spacing>
+
+ <widget>
+ <class>GtkMenuBar</class>
+ <name>mainmenubar</name>
+ <shadow_type>GTK_SHADOW_OUT</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>file</name>
+ <label>_File</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>file_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>file_open</name>
+ <tooltip>Load a MIX file</tooltip>
+ <accelerator>
+ <modifiers>GDK_MOD1_MASK</modifiers>
+ <key>GDK_F3</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>on_file_open_activate</handler>
+ <last_modification_time>Tue, 20 Feb 2001 22:37:58 GMT</last_modification_time>
+ </signal>
+ <label>_Load...</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>file_exit</name>
+ <tooltip>Exit application</tooltip>
+ <accelerator>
+ <modifiers>GDK_MOD1_MASK</modifiers>
+ <key>GDK_Q</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>on_file_exit_activate</handler>
+ <last_modification_time>Tue, 20 Feb 2001 22:37:58 GMT</last_modification_time>
+ </signal>
+ <label>_Exit</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>debug</name>
+ <label>Debu_g</label>
+ <right_justify>False</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>debug_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>debug_run</name>
+ <accelerator>
+ <modifiers>GDK_MOD1_MASK</modifiers>
+ <key>GDK_R</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>on_debug_run_activate</handler>
+ <last_modification_time>Sat, 10 Mar 2001 11:35:16 GMT</last_modification_time>
+ </signal>
+ <label>_Run</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>debug_next</name>
+ <accelerator>
+ <modifiers>GDK_MOD1_MASK</modifiers>
+ <key>GDK_N</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>on_debug_next_activate</handler>
+ <last_modification_time>Sat, 10 Mar 2001 11:35:16 GMT</last_modification_time>
+ </signal>
+ <label>_Next</label>
+ <right_justify>False</right_justify>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>clear_breakpoints</name>
+ <tooltip>Clear all set breakpoints</tooltip>
+ <accelerator>
+ <modifiers>GDK_MOD1_MASK</modifiers>
+ <key>GDK_C</key>
+ <signal>activate</signal>
+ </accelerator>
+ <signal>
+ <name>activate</name>
+ <handler>on_clear_breakpoints_activate</handler>
+ <last_modification_time>Thu, 15 Mar 2001 23:26:49 GMT</last_modification_time>
+ </signal>
+ <label>_Clear breakpoints</label>
+ <right_justify>False</right_justify>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>help</name>
+ <label>_Help</label>
+ <right_justify>True</right_justify>
+
+ <widget>
+ <class>GtkMenu</class>
+ <name>help_menu</name>
+
+ <widget>
+ <class>GtkMenuItem</class>
+ <name>about</name>
+ <signal>
+ <name>activate</name>
+ <handler>on_about_activate</handler>
+ <last_modification_time>Tue, 13 Mar 2001 01:37:20 GMT</last_modification_time>
+ </signal>
+ <label>_About...</label>
+ <right_justify>True</right_justify>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkToolbar</class>
+ <name>main_toolbar</name>
+ <orientation>GTK_ORIENTATION_HORIZONTAL</orientation>
+ <type>GTK_TOOLBAR_ICONS</type>
+ <space_size>5</space_size>
+ <space_style>GTK_TOOLBAR_SPACE_LINE</space_style>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <tooltips>True</tooltips>
+ <child>
+ <padding>1</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>inner_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkNotebook</class>
+ <name>main_notebook</name>
+ <can_focus>True</can_focus>
+ <show_tabs>True</show_tabs>
+ <show_border>True</show_border>
+ <tab_pos>GTK_POS_TOP</tab_pos>
+ <scrollable>False</scrollable>
+ <tab_hborder>2</tab_hborder>
+ <tab_vborder>2</tab_vborder>
+ <popup_enable>False</popup_enable>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>mixvm_widget</name>
+ <width>375</width>
+ <height>287</height>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rJ_entry</name>
+ <x>304</x>
+ <y>88</y>
+ <width>60</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:45:00 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rA_entry</name>
+ <x>40</x>
+ <y>24</y>
+ <width>120</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Mon, 12 Mar 2001 23:09:49 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rX_entry</name>
+ <x>248</x>
+ <y>24</y>
+ <width>120</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:43:29 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rI2_entry</name>
+ <x>40</x>
+ <y>144</y>
+ <width>60</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:45:39 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rI1_entry</name>
+ <x>40</x>
+ <y>88</y>
+ <width>60</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:43:44 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rI3_entry</name>
+ <x>40</x>
+ <y>200</y>
+ <width>60</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:46:37 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rI4_entry</name>
+ <x>168</x>
+ <y>88</y>
+ <width>60</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:44:21 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rI6_entry</name>
+ <x>168</x>
+ <y>200</y>
+ <width>60</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:46:58 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label100</name>
+ <x>8</x>
+ <y>91</y>
+ <width>31</width>
+ <height>16</height>
+ <label>I1</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label102</name>
+ <x>8</x>
+ <y>200</y>
+ <width>31</width>
+ <height>16</height>
+ <label>I3</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label101</name>
+ <x>8</x>
+ <y>144</y>
+ <width>31</width>
+ <height>16</height>
+ <label>I2</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label103</name>
+ <x>136</x>
+ <y>88</y>
+ <width>32</width>
+ <height>16</height>
+ <label>I4</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label104</name>
+ <x>136</x>
+ <y>144</y>
+ <width>31</width>
+ <height>16</height>
+ <label>I5</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label105</name>
+ <x>136</x>
+ <y>200</y>
+ <width>31</width>
+ <height>16</height>
+ <label>I6</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label98</name>
+ <x>216</x>
+ <y>24</y>
+ <width>31</width>
+ <height>16</height>
+ <label>X</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label97</name>
+ <x>8</x>
+ <y>24</y>
+ <width>31</width>
+ <height>16</height>
+ <label>A</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>vseparator2</name>
+ <x>0</x>
+ <y>8</y>
+ <width>16</width>
+ <height>263</height>
+ </widget>
+
+ <widget>
+ <class>GtkHSeparator</class>
+ <name>hseparator3</name>
+ <x>6</x>
+ <y>1</y>
+ <width>627</width>
+ <height>16</height>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>vseparator3</name>
+ <x>626</x>
+ <y>8</y>
+ <width>16</width>
+ <height>267</height>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label99</name>
+ <x>272</x>
+ <y>88</y>
+ <width>31</width>
+ <height>16</height>
+ <label>J</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkHSeparator</class>
+ <name>hseparator2</name>
+ <x>6</x>
+ <y>265</y>
+ <width>627</width>
+ <height>16</height>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label159</name>
+ <x>8</x>
+ <y>248</y>
+ <width>64</width>
+ <height>16</height>
+ <label>Elapsed:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label158</name>
+ <x>128</x>
+ <y>248</y>
+ <width>64</width>
+ <height>16</height>
+ <label>Program:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label157</name>
+ <x>256</x>
+ <y>248</y>
+ <width>48</width>
+ <height>16</height>
+ <label>Uptime:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>vseparator1</name>
+ <x>376</x>
+ <y>10</y>
+ <width>16</width>
+ <height>263</height>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>rI5_entry</name>
+ <x>168</x>
+ <y>144</y>
+ <width>60</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>button_press_event</name>
+ <handler>on_register_click</handler>
+ <last_modification_time>Sun, 11 Mar 2001 11:46:05 GMT</last_modification_time>
+ </signal>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>loc_entry</name>
+ <x>300</x>
+ <y>200</y>
+ <width>40</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label167</name>
+ <x>256</x>
+ <y>200</y>
+ <width>48</width>
+ <height>16</height>
+ <label>LOC</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>loc_arrow</name>
+ <x>346</x>
+ <y>202</y>
+ <width>29</width>
+ <height>18</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_loc_arrow_clicked</handler>
+ <last_modification_time>Fri, 09 Mar 2001 20:18:22 GMT</last_modification_time>
+ </signal>
+ <label>-&gt;</label>
+ <relief>GTK_RELIEF_NONE</relief>
+ </widget>
+
+ <widget>
+ <class>GtkHSeparator</class>
+ <name>hseparator1</name>
+ <x>8</x>
+ <y>232</y>
+ <width>377</width>
+ <height>16</height>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>program_label</name>
+ <x>184</x>
+ <y>248</y>
+ <width>56</width>
+ <height>16</height>
+ <label>000000</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>elapsed_label</name>
+ <x>64</x>
+ <y>248</y>
+ <width>48</width>
+ <height>16</height>
+ <label>000000</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>uptime_label</name>
+ <x>296</x>
+ <y>248</y>
+ <width>72</width>
+ <height>16</height>
+ <label>00000000</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkCheckButton</class>
+ <name>over_toggle</name>
+ <x>288</x>
+ <y>168</y>
+ <width>88</width>
+ <height>16</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>on_overflow_toggled</handler>
+ <last_modification_time>Tue, 06 Mar 2001 21:32:39 GMT</last_modification_time>
+ </signal>
+ <label>Overflow</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>lesser_radio</name>
+ <x>264</x>
+ <y>128</y>
+ <width>35</width>
+ <height>24</height>
+ <tooltip>Comparison flag: lesser</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>on_cmp_l_toggled</handler>
+ <last_modification_time>Tue, 06 Mar 2001 21:21:51 GMT</last_modification_time>
+ </signal>
+ <label>L</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>cmp_group</group>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>equal_radio</name>
+ <x>304</x>
+ <y>128</y>
+ <width>31</width>
+ <height>24</height>
+ <tooltip>Comparison flag: equal</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>on_cmp_e_toggled</handler>
+ <last_modification_time>Tue, 06 Mar 2001 21:22:04 GMT</last_modification_time>
+ </signal>
+ <label>E</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>cmp_group</group>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>greater_radio</name>
+ <x>336</x>
+ <y>128</y>
+ <width>32</width>
+ <height>24</height>
+ <tooltip>Comparison flag: greater</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>toggled</name>
+ <handler>on_cmp_g_toggled</handler>
+ <last_modification_time>Tue, 06 Mar 2001 21:21:40 GMT</last_modification_time>
+ </signal>
+ <label>G</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>cmp_group</group>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>memory_scroll</name>
+ <x>398</x>
+ <y>16</y>
+ <width>225</width>
+ <height>248</height>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+
+ <widget>
+ <class>GtkCList</class>
+ <name>memory_cells</name>
+ <width>195</width>
+ <height>248</height>
+ <tooltip>Click cell to change value</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>select_row</name>
+ <handler>on_memory_cells_select_row</handler>
+ <after>True</after>
+ <last_modification_time>Tue, 13 Mar 2001 07:38:52 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>click_column</name>
+ <handler>on_memory_cells_click_column</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:18:57 GMT</last_modification_time>
+ </signal>
+ <columns>2</columns>
+ <column_widths>53,135</column_widths>
+ <selection_mode>GTK_SELECTION_SINGLE</selection_mode>
+ <show_titles>True</show_titles>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label165</name>
+ <label>address</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label166</name>
+ <label>contents</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>label105</name>
+ <label>_MIX</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>mixal_scrol</name>
+ <hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+
+ <widget>
+ <class>GtkCList</class>
+ <name>mixal_clist</name>
+ <tooltip>Click to toggle breakpoint</tooltip>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>select_row</name>
+ <handler>on_mixal_select_row</handler>
+ <after>True</after>
+ <last_modification_time>Sun, 11 Mar 2001 01:15:28 GMT</last_modification_time>
+ </signal>
+ <columns>2</columns>
+ <column_widths>152,80</column_widths>
+ <selection_mode>GTK_SELECTION_SINGLE</selection_mode>
+ <show_titles>True</show_titles>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label213</name>
+ <label>memory</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label214</name>
+ <label>source</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>label106</name>
+ <label>MI_XAL</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkNotebook</class>
+ <name>devices_notebook</name>
+ <width>404</width>
+ <height>254</height>
+ <can_focus>True</can_focus>
+ <show_tabs>True</show_tabs>
+ <show_border>True</show_border>
+ <tab_pos>GTK_POS_RIGHT</tab_pos>
+ <scrollable>True</scrollable>
+ <tab_hborder>2</tab_hborder>
+ <tab_vborder>2</tab_vborder>
+ <popup_enable>True</popup_enable>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>label156</name>
+ <label>term</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>Notebook:tab</child_name>
+ <name>devices_label</name>
+ <label>De_vices</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow25</name>
+ <border_width>2</border_width>
+ <hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkViewport</class>
+ <name>viewport1</name>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>prompt_vbox</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>mixlog_scrolledwindow</name>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkText</class>
+ <name>command_log</name>
+ <editable>False</editable>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>command_prompt</name>
+ <tooltip>Enter MIXVM command here</tooltip>
+ <can_focus>True</can_focus>
+ <has_focus>True</has_focus>
+ <signal>
+ <name>activate</name>
+ <handler>on_mixvm_cmd_entry_activate</handler>
+ <last_modification_time>Thu, 22 Feb 2001 23:26:28 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkStatusbar</class>
+ <name>main_statusbar</name>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>word_dialog</name>
+ <visible>False</visible>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 13 Mar 2001 00:53:39 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>destroy_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 13 Mar 2001 00:55:38 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>delete_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 13 Mar 2001 00:56:33 GMT</last_modification_time>
+ </signal>
+ <title>Enter value</title>
+ <type>GTK_WINDOW_DIALOG</type>
+ <position>GTK_WIN_POS_MOUSE</position>
+ <modal>True</modal>
+ <default_width>250</default_width>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox5</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area5</name>
+ <border_width>10</border_width>
+ <width>250</width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <name>hbuttonbox5</name>
+ <width>250</width>
+ <layout_style>GTK_BUTTONBOX_DEFAULT_STYLE</layout_style>
+ <spacing>30</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>word_reset</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_word_reset_clicked</handler>
+ <last_modification_time>Mon, 12 Mar 2001 22:40:33 GMT</last_modification_time>
+ </signal>
+ <label>Reset</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>word_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_word_ok_clicked</handler>
+ <last_modification_time>Mon, 12 Mar 2001 22:40:45 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>word_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_word_cancel_clicked</handler>
+ <last_modification_time>Mon, 12 Mar 2001 23:18:49 GMT</last_modification_time>
+ </signal>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFixed</class>
+ <name>word_layout</name>
+ <width>250</width>
+ <height>97</height>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_decimal</name>
+ <x>88</x>
+ <y>32</y>
+ <width>143</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <has_focus>True</has_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_dec_key_press</handler>
+ <after>True</after>
+ <last_modification_time>Mon, 12 Mar 2001 22:37:13 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>11</text_max_length>
+ <text>0</text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_b2</name>
+ <x>136</x>
+ <y>64</y>
+ <width>22</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_byte_key_press</handler>
+ <after>True</after>
+ <last_modification_time>Mon, 12 Mar 2001 22:38:56 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>3</text_max_length>
+ <text>00</text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_b3</name>
+ <x>160</x>
+ <y>64</y>
+ <width>22</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_byte_key_press</handler>
+ <after>True</after>
+ <last_modification_time>Mon, 12 Mar 2001 22:39:26 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>3</text_max_length>
+ <text>00</text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_b4</name>
+ <x>184</x>
+ <y>64</y>
+ <width>22</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_byte_key_press</handler>
+ <after>True</after>
+ <last_modification_time>Mon, 12 Mar 2001 22:39:50 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>3</text_max_length>
+ <text>00</text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_b5</name>
+ <x>208</x>
+ <y>64</y>
+ <width>22</width>
+ <height>22</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_byte_key_press</handler>
+ <after>True</after>
+ <last_modification_time>Mon, 12 Mar 2001 22:40:09 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>3</text_max_length>
+ <text>00</text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_b1</name>
+ <x>112</x>
+ <y>64</y>
+ <width>22</width>
+ <height>22</height>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_byte_key_press</handler>
+ <after>True</after>
+ <last_modification_time>Mon, 12 Mar 2001 22:38:24 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>3</text_max_length>
+ <text>00</text>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>word_sign</name>
+ <x>88</x>
+ <y>64</y>
+ <width>16</width>
+ <height>24</height>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>key_press_event</name>
+ <handler>on_word_sign_key_press</handler>
+ <last_modification_time>Tue, 13 Mar 2001 00:15:28 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>1</text_max_length>
+ <text>+</text>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label61</name>
+ <x>22</x>
+ <y>67</y>
+ <width>41</width>
+ <height>16</height>
+ <label>Bytes</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>word_label</name>
+ <x>16</x>
+ <y>8</y>
+ <width>216</width>
+ <height>16</height>
+ <label>Enter value</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label60</name>
+ <x>16</x>
+ <y>34</y>
+ <width>67</width>
+ <height>20</height>
+ <label>Decimal</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>about_dialog</name>
+ <width>368</width>
+ <height>99</height>
+ <visible>False</visible>
+ <signal>
+ <name>delete_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 13 Mar 2001 13:13:42 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>destroy_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 13 Mar 2001 13:14:02 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Tue, 13 Mar 2001 13:14:25 GMT</last_modification_time>
+ </signal>
+ <title>MDK</title>
+ <type>GTK_WINDOW_DIALOG</type>
+ <position>GTK_WIN_POS_CENTER</position>
+ <modal>True</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkLayout</class>
+ <name>layout1</name>
+ <width>375</width>
+ <height>190</height>
+ <area_width>200</area_width>
+ <area_height>120</area_height>
+ <hstep>0</hstep>
+ <vstep>0</vstep>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label222</name>
+ <x>56</x>
+ <y>16</y>
+ <width>247</width>
+ <height>16</height>
+ <label>GNU MIX Development Kit</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>version_label</name>
+ <x>152</x>
+ <y>40</y>
+ <width>56</width>
+ <height>16</height>
+ <label>label223</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label224</name>
+ <x>0</x>
+ <y>64</y>
+ <width>358</width>
+ <height>16</height>
+ <label> Copyright (C) 2001 Free Software Foundation, Inc.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+
+ <widget>
+ <class>GtkHSeparator</class>
+ <name>hseparator4</name>
+ <x>8</x>
+ <y>0</y>
+ <width>356</width>
+ <height>16</height>
+ </widget>
+
+ <widget>
+ <class>GtkHSeparator</class>
+ <name>hseparator5</name>
+ <x>8</x>
+ <y>80</y>
+ <width>356</width>
+ <height>16</height>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>vseparator4</name>
+ <x>0</x>
+ <y>7</y>
+ <width>16</width>
+ <height>83</height>
+ </widget>
+
+ <widget>
+ <class>GtkVSeparator</class>
+ <name>vseparator5</name>
+ <x>352</x>
+ <y>8</y>
+ <width>16</width>
+ <height>83</height>
+ </widget>
+ </widget>
+</widget>
+
+<widget>
+ <class>GtkDialog</class>
+ <name>goto_dialog</name>
+ <width>190</width>
+ <height>116</height>
+ <visible>False</visible>
+ <signal>
+ <name>destroy_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:39:17 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>delete_event</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:39:41 GMT</last_modification_time>
+ </signal>
+ <signal>
+ <name>destroy</name>
+ <handler>gtk_widget_hide</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:40:15 GMT</last_modification_time>
+ </signal>
+ <title>Go to memory cell</title>
+ <type>GTK_WINDOW_DIALOG</type>
+ <position>GTK_WIN_POS_MOUSE</position>
+ <modal>True</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>False</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>Dialog:vbox</child_name>
+ <name>dialog-vbox6</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <child_name>Dialog:action_area</child_name>
+ <name>dialog-action_area6</name>
+ <border_width>10</border_width>
+ <homogeneous>True</homogeneous>
+ <spacing>5</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <name>hbuttonbox6</name>
+ <layout_style>GTK_BUTTONBOX_DEFAULT_STYLE</layout_style>
+ <spacing>30</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>goto_cancel</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_goto_cancel_clicked</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:24:59 GMT</last_modification_time>
+ </signal>
+ <label>Cancel</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>goto_ok</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <signal>
+ <name>clicked</name>
+ <handler>on_goto_ok_clicked</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:25:23 GMT</last_modification_time>
+ </signal>
+ <label>OK</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox1</name>
+ <border_width>12</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label225</name>
+ <label>Go to address:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>goto_entry</name>
+ <width>44</width>
+ <can_focus>True</can_focus>
+ <has_focus>True</has_focus>
+ <signal>
+ <name>activate</name>
+ <handler>on_goto_ok_clicked</handler>
+ <last_modification_time>Wed, 14 Mar 2001 14:52:26 GMT</last_modification_time>
+ </signal>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>4</text_max_length>
+ <text></text>
+ <child>
+ <padding>10</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/mixgtk/mixgtk_cmd_dispatcher.c b/mixgtk/mixgtk_cmd_dispatcher.c
new file mode 100644
index 0000000..11acc1d
--- /dev/null
+++ b/mixgtk/mixgtk_cmd_dispatcher.c
@@ -0,0 +1,314 @@
+/* -*-c-*- -------------- mixgtk_cmd_dispatcher.c :
+ * Implementation of the functions declared in mixgtk_cmd_dispatcher.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/15 16:01:43 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#define _GNU_SOURCE 1
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mixlib/mix_vm_command.h>
+#include "mixgtk_cmd_dispatcher.h"
+#include "mixgtk_mixvm.h"
+#include "mixgtk_mixal.h"
+
+
+/* a mix vm command dispatcher */
+struct mixgtk_dispatch_
+{
+ mix_vm_cmd_dispatcher_t *dispatcher;
+ FILE *out;
+ char *out_buffer;
+ size_t out_buffer_size;
+ GtkWidget *prompt;
+ GtkWidget *log;
+ GtkWidget *status;
+ guint context;
+ GCompletion *completions;
+};
+
+static struct mixgtk_dispatch_ dis_data_ = {NULL};
+
+/* completions */
+static void
+init_completions_ (void)
+{
+ GList *cmds = NULL;
+ gint k;
+
+ dis_data_.completions = g_completion_new (NULL);
+ for (k = 0; k < MIX_CMD_INVALID; ++k)
+ cmds = g_list_append (cmds, (gpointer) mix_vm_command_to_string (k));
+ g_completion_add_items (dis_data_.completions, cmds);
+}
+
+/* global hooks for the command dispatcher */
+static void
+global_pre_hook_ (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd, const gchar *arg, gpointer data)
+{
+ if (cmd < MIX_CMD_INVALID)
+ {
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ "MIX> ", -1);
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ mix_vm_command_to_string (cmd), -1);
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ " ", -1);
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ arg, -1);
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ "\n", -1);
+ }
+ else
+ {
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ _("\n*** Invalid command ***\n"), -1);
+ }
+}
+
+static void
+global_post_hook_ (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd, const gchar *arg, gpointer data)
+{
+ fflush (dis_data_.out);
+ if (cmd < MIX_CMD_INVALID)
+ {
+ gtk_text_insert (GTK_TEXT (dis_data_.log), NULL, NULL, NULL,
+ dis_data_.out_buffer, dis_data_.out_buffer_size);
+ }
+ rewind (dis_data_.out);
+ mixgtk_mixvm_update_vm_widgets ();
+}
+
+static void
+load_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
+ gpointer data)
+{
+ static glong id = -1;
+
+ if (mix_vm_cmd_dispatcher_get_last_result (dis))
+ {
+ gchar *file = g_strdup (arg);
+ mixgtk_mixal_load_file ();
+ mixgtk_mixal_update ();
+
+ if (id != -1)
+ gtk_statusbar_remove (GTK_STATUSBAR (dis_data_.status),
+ dis_data_.context, (guint)id);
+ id =
+ gtk_statusbar_push (GTK_STATUSBAR (dis_data_.status), dis_data_.context,
+ file);
+ }
+}
+
+static void
+run_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
+ gpointer data)
+{
+ mixgtk_mixal_update ();
+}
+
+static void
+next_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
+ gpointer data)
+{
+ mixgtk_mixal_update ();
+}
+
+static void
+linebp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
+ gpointer data)
+{
+ if (arg && strlen (arg)) mixgtk_mixal_update_bp_at_line (atoi (arg));
+}
+
+static void
+addrbp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
+ gpointer data)
+{
+ if (arg && strlen (arg)) mixgtk_mixal_update_bp_at_address (atoi (arg));
+}
+
+static void
+allbp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
+ gpointer data)
+{
+ mixgtk_mixal_update_bp_all ();
+}
+
+
+static void
+install_hooks_ (void)
+{
+ mix_vm_cmd_dispatcher_global_pre_hook (dis_data_.dispatcher,
+ global_pre_hook_, NULL);
+ mix_vm_cmd_dispatcher_global_post_hook (dis_data_.dispatcher,
+ global_post_hook_, NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_LOAD, load_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_RUN, run_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_NEXT, next_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_SBP, linebp_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_CBP, linebp_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_SBPA, addrbp_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_CBPA, addrbp_post_hook_,
+ NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
+ MIX_CMD_CABP, allbp_post_hook_,
+ NULL);
+}
+
+
+/* initialise the command dispatcher */
+gboolean
+mixgtk_cmd_dispatcher_init (void)
+{
+ if (!dis_data_.prompt)
+ {
+ dis_data_.prompt = mixgtk_widget_factory_get (MIXGTK_WIDGET_PROMPT);
+ g_return_val_if_fail (dis_data_.prompt != NULL, FALSE);
+ dis_data_.log = mixgtk_widget_factory_get (MIXGTK_WIDGET_LOG);
+ g_return_val_if_fail (dis_data_.log != NULL, FALSE);
+ }
+
+ if (!dis_data_.dispatcher)
+ {
+ FILE *out = open_memstream (&(dis_data_.out_buffer),
+ &(dis_data_.out_buffer_size));
+ g_return_val_if_fail (out != NULL, FALSE);
+ dis_data_.out = out;
+ dis_data_.dispatcher = mix_vm_cmd_dispatcher_new (out, out);
+ mix_vm_cmd_dispatcher_print_time (dis_data_.dispatcher, FALSE);
+ install_hooks_ ();
+ }
+
+ if (!dis_data_.status)
+ {
+ dis_data_.status = mixgtk_widget_factory_get (MIXGTK_WIDGET_STATUSBAR);
+ g_return_val_if_fail (dis_data_.status != NULL, FALSE);
+ dis_data_.context = gtk_statusbar_get_context_id (GTK_STATUSBAR
+ (dis_data_.status),
+ "cmd_dis_context");
+ }
+
+ if (!dis_data_.completions) init_completions_ ();
+
+ return TRUE;
+}
+
+/* dispatch an externally provided command */
+void
+mixgtk_cmd_dispatcher_dispatch (const gchar *command)
+{
+ GtkWidget *entry = dis_data_.prompt;
+ g_return_if_fail (command != NULL);
+ g_assert (entry != NULL);
+ gtk_entry_set_text (GTK_ENTRY (entry), command);
+ on_mixvm_cmd_entry_activate (entry, NULL);
+}
+
+/* get times */
+void
+mixgtk_cmd_dispatcher_get_times (gint *uptime, gint *progtime, gint *laptime)
+{
+ if (uptime != NULL)
+ *uptime = mix_vm_cmd_dispatcher_get_uptime (dis_data_.dispatcher);
+ if (progtime != NULL)
+ *progtime = mix_vm_cmd_dispatcher_get_progtime (dis_data_.dispatcher);
+ if (laptime != NULL)
+ *laptime = mix_vm_cmd_dispatcher_get_laptime (dis_data_.dispatcher);
+}
+
+/* get the underlying vm */
+extern mix_vm_t *
+mixgtk_cmd_dispatcher_get_vm (void)
+{
+ return (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (dis_data_.dispatcher);
+}
+
+/* process new command */
+void
+on_mixvm_cmd_entry_activate (GtkWidget *w, gpointer e)
+{
+ gchar *text;
+ GList *cmds = NULL;
+ gchar *prefix = NULL;
+
+ text = gtk_entry_get_text (GTK_ENTRY (w));
+
+ if (mix_vm_command_from_string (g_strchomp (text)) != MIX_CMD_INVALID)
+ {
+ mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text);
+ gtk_entry_set_text (GTK_ENTRY (w), "");
+ return;
+ }
+
+ cmds = g_completion_complete (dis_data_.completions, text, &prefix);
+
+ if (prefix != NULL)
+ {
+ gtk_entry_set_text (GTK_ENTRY (w), prefix);
+ g_free (prefix);
+ if (g_list_length (cmds) > 1)
+ {
+ gint k = 0;
+ gtk_text_insert (GTK_TEXT (dis_data_.log),
+ NULL, NULL, NULL, "Completions:\n", -1);
+ while (cmds)
+ {
+ ++k;
+ gtk_text_insert (GTK_TEXT (dis_data_.log),
+ NULL, NULL, NULL,
+ (gchar *)(cmds->data), -1);
+ gtk_text_insert (GTK_TEXT (dis_data_.log),
+ NULL, NULL, NULL, " ", -1);
+ if (k%5 == 0)
+ gtk_text_insert (GTK_TEXT (dis_data_.log),
+ NULL, NULL, NULL, "\n", -1);
+
+ cmds = cmds->next;
+ }
+ if (k%5 != 0)
+ gtk_text_insert (GTK_TEXT (dis_data_.log),
+ NULL, NULL, NULL, "\n", -1);
+ }
+ else
+ gtk_entry_append_text (GTK_ENTRY (w), " ");
+ }
+ else
+ {
+ mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text);
+ gtk_entry_set_text (GTK_ENTRY (w), "");
+ }
+}
diff --git a/mixgtk/mixgtk_cmd_dispatcher.h b/mixgtk/mixgtk_cmd_dispatcher.h
new file mode 100644
index 0000000..686ba4d
--- /dev/null
+++ b/mixgtk/mixgtk_cmd_dispatcher.h
@@ -0,0 +1,55 @@
+/* -*-c-*- ---------------- mixgtk_cmd_dispatcher.h :
+ * functions to access the command dispatcher
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/09 22:08:08 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_CMD_DISPATCHER_H
+#define MIXGTK_CMD_DISPATCHER_H
+
+#include <mixlib/mix_vm.h>
+#include "mixgtk_widgets.h"
+
+/* initialise the command dispatcher */
+extern gboolean
+mixgtk_cmd_dispatcher_init (void);
+
+/* dispatch an externally provided command */
+extern void
+mixgtk_cmd_dispatcher_dispatch (const gchar *command);
+
+/* get times */
+extern void
+mixgtk_cmd_dispatcher_get_times (gint *uptime, gint *progtime, gint *laptime);
+
+/* get the underlying vm */
+extern mix_vm_t *
+mixgtk_cmd_dispatcher_get_vm (void);
+
+/* make gtk signal callbacks accessible to glade */
+/* new command handler */
+extern void
+on_mixvm_cmd_entry_activate (GtkWidget *w, gpointer e);
+
+
+
+#endif /* MIXGTK_CMD_DISPATCHER_H */
+
diff --git a/mixgtk/mixgtk_device.c b/mixgtk/mixgtk_device.c
new file mode 100644
index 0000000..2e231a4
--- /dev/null
+++ b/mixgtk/mixgtk_device.c
@@ -0,0 +1,155 @@
+/* -*-c-*- ---------------- mixgtk_device.c :
+ * actual types for mixgtk devices
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/05 01:13:40 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <mixlib/xmix_device.h>
+#include "mixgtk_device.h"
+
+/* device container */
+static GtkNotebook *container_ = NULL;
+/* virtual machine */
+static mix_vm_t *vm_ = NULL;
+
+/* a mixgtk device */
+struct mixgtk_device_t
+{
+ mix_device_t device;
+ char *buffer;
+ size_t buffer_len;
+ GtkText *widget;
+ gint pos;
+};
+
+/* callbacks for output devices */
+static gboolean
+write_out_ (mix_device_t *dev, const mix_word_t *block)
+{
+ struct mixgtk_device_t *gtkdev;
+
+ if (!((DEF_DEV_VTABLE_->write) (dev, block))) return FALSE;
+ gtkdev = (struct mixgtk_device_t *) dev;
+ if (gtkdev->buffer_len > 0)
+ {
+ gtk_text_insert (gtkdev->widget, NULL, NULL, NULL,
+ gtkdev->buffer, gtkdev->buffer_len);
+ rewind (mix_io_to_FILE (gtkdev->device.file));
+ gtk_notebook_set_page (container_, gtkdev->pos);
+ gtk_widget_draw (GTK_WIDGET (container_), NULL);
+ }
+ return TRUE;
+}
+
+static mix_device_vtable_t MIXGTK_OUT_VTABLE_;
+
+/* create a new mixgtk device */
+static struct mixgtk_device_t *
+mixgtk_device_new_ (mix_device_type_t type)
+{
+ struct mixgtk_device_t *dev = NULL;
+
+ g_return_val_if_fail (type < mix_dev_INVALID, NULL);
+
+ if (MODES_[type] == mix_dev_CHAR && FMODES_[type] == mix_io_WRITE)
+ {
+ FILE *f;
+ dev = g_new (struct mixgtk_device_t, 1);
+ f = open_memstream (&(dev->buffer), &(dev->buffer_len));
+ g_assert (f);
+ dev->device.file = mix_io_new (f);
+ dev->device.type = type;
+ dev->device.vtable = &MIXGTK_OUT_VTABLE_;
+ dev->widget = (GtkText *)gtk_text_new (NULL, NULL);
+ g_assert (dev->widget);
+ gtk_text_set_editable (dev->widget, FALSE);
+ }
+ return dev;
+}
+
+/* connect a device */
+static void
+mixgtk_device_connect_ (struct mixgtk_device_t *dev)
+{
+ static gint last_pos = 0;
+ GtkWidget *label = gtk_label_new (DEF_NAMES_[dev->device.type]);
+ GtkWidget *box = gtk_hbox_new (0, 0);
+ GtkWidget *scroll = gtk_vscrollbar_new (dev->widget->vadj);
+ g_assert (label);
+ g_assert (box);
+ gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (dev->widget),
+ TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (box), scroll, FALSE, FALSE, 0);
+ dev->pos = last_pos++;
+ gtk_notebook_insert_page (container_, box, label, dev->pos);
+ gtk_widget_show (box);
+ gtk_widget_show (label);
+ gtk_widget_show (scroll);
+ gtk_widget_show (GTK_WIDGET (dev->widget));
+ gtk_widget_draw (GTK_WIDGET (container_), NULL);
+ (void) mix_vm_connect_device (vm_, (mix_device_t *)dev);
+}
+
+/* init default devices */
+gboolean
+mixgtk_device_init (GtkNotebook *container, mix_vm_t *vm)
+{
+ static mix_device_type_t def_types[] = {
+ mix_dev_CONSOLE, mix_dev_PRINTER, mix_dev_PAPER_TAPE, mix_dev_INVALID
+ };
+
+ gint k = 0;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (vm != NULL, FALSE);
+ container_ = container;
+ vm_ = vm;
+
+ /* remove dummy page from container */
+ gtk_notebook_remove_page (container_, 0);
+
+ /* initialise vtables */
+ MIXGTK_OUT_VTABLE_.write = write_out_;
+ MIXGTK_OUT_VTABLE_.read = DEF_DEV_VTABLE_->read;
+ MIXGTK_OUT_VTABLE_.ioc = DEF_DEV_VTABLE_->ioc;
+ MIXGTK_OUT_VTABLE_.busy = DEF_DEV_VTABLE_->busy;
+
+ /* connect default devices */
+ while (def_types[k] != mix_dev_INVALID)
+ {
+ struct mixgtk_device_t *dev = mixgtk_device_new_ (def_types[k]);
+ if (dev != NULL)
+ mixgtk_device_connect_ (dev);
+ ++k;
+ }
+
+ /* set to first page */
+ gtk_notebook_set_page (container_, 0);
+
+ return TRUE;
+}
+
+/* connect a new (file-based) device */
+gboolean
+mixgtk_device_connect (mix_device_type_t type, const gchar *name);
diff --git a/mixgtk/mixgtk_device.h b/mixgtk/mixgtk_device.h
new file mode 100644
index 0000000..7c21238
--- /dev/null
+++ b/mixgtk/mixgtk_device.h
@@ -0,0 +1,42 @@
+/* -*-c-*- ---------------- mixgtk_device.h :
+ * Block devices used by mixgtk
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/04 23:43:59 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_DEVICE_H
+#define MIXGTK_DEVICE_H
+
+#include <gtk/gtk.h>
+#include <mixlib/mix_vm.h>
+#include <mixlib/mix_device.h>
+
+/* init default devices */
+extern gboolean
+mixgtk_device_init (GtkNotebook *container, mix_vm_t *vm);
+
+
+/* connect a new (file-based) device */
+extern gboolean
+mixgtk_device_connect (mix_device_type_t type, const gchar *name);
+
+#endif /* MIXGTK_DEVICE_H */
+
diff --git a/mixgtk/mixgtk_gen_handlers.c b/mixgtk/mixgtk_gen_handlers.c
new file mode 100644
index 0000000..9f23310
--- /dev/null
+++ b/mixgtk/mixgtk_gen_handlers.c
@@ -0,0 +1,95 @@
+/* -*-c-*- -------------- mixgtk_gen_handlers.c :
+ * Implementation of the functions declared in mixgtk_gen_handlers.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/16 00:30:40 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <mixlib/mix_vm_command.h>
+#include "mixgtk_gen_handlers.h"
+#include "mixgtk_cmd_dispatcher.h"
+
+void
+on_main_window_destroy (GtkWidget *w, gpointer data)
+{
+ gtk_main_quit ();
+}
+
+static void
+on_file_open_ok_ (GtkWidget *w, gpointer fs)
+{
+ const gchar *file = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
+ gchar *command = g_strdup_printf ("%s %s",
+ mix_vm_command_to_string (MIX_CMD_LOAD),
+ file);
+ gtk_widget_destroy (GTK_WIDGET (fs));
+ mixgtk_cmd_dispatcher_dispatch (command);
+ g_free (command);
+}
+
+static void
+on_file_open_destroy_ (GtkWidget *w, gpointer data)
+{
+ gtk_grab_remove (GTK_WIDGET (w));
+}
+
+void
+on_file_open_activate (GtkWidget *w, gpointer data)
+{
+ GtkWidget *file = gtk_file_selection_new ("Open program");
+ gtk_signal_connect (GTK_OBJECT (file), "destroy",
+ (GtkSignalFunc) on_file_open_destroy_,
+ GTK_OBJECT (file));
+ gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file)->ok_button),
+ "clicked", (GtkSignalFunc) on_file_open_ok_,
+ GTK_OBJECT (file));
+ gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
+ (file)->cancel_button),
+ "clicked", (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (file));
+ gtk_widget_show (file);
+ gtk_grab_add (file);
+}
+
+void
+on_debug_run_activate (GtkWidget *w, gpointer p)
+{
+ mixgtk_cmd_dispatcher_dispatch (mix_vm_command_to_string (MIX_CMD_RUN));
+}
+
+void
+on_debug_next_activate (GtkWidget *w, gpointer p)
+{
+ mixgtk_cmd_dispatcher_dispatch (mix_vm_command_to_string (MIX_CMD_NEXT));
+}
+
+
+void
+on_file_exit_activate (GtkWidget *w, gpointer data)
+{
+ gtk_main_quit ();
+}
+
+
+void
+on_clear_breakpoints_activate (GtkWidget *w, gpointer data)
+{
+ mixgtk_cmd_dispatcher_dispatch (mix_vm_command_to_string (MIX_CMD_CABP));
+}
+
diff --git a/mixgtk/mixgtk_gen_handlers.h b/mixgtk/mixgtk_gen_handlers.h
new file mode 100644
index 0000000..6e0a45d
--- /dev/null
+++ b/mixgtk/mixgtk_gen_handlers.h
@@ -0,0 +1,46 @@
+/* -*-c-*- ---------------- mixgtk_gen_handlers.h :
+ * general signal handlers declarations
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/16 00:29:45 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_GEN_HANDLERS_H
+#define MIXGTK_GEN_HANDLERS_H
+
+#include <gtk/gtk.h>
+
+extern void
+on_main_window_destroy (GtkWidget *w, gpointer data);
+
+extern void
+on_file_open_activate (GtkWidget *w, gpointer data);
+
+extern void
+on_file_exit_activate (GtkWidget *w, gpointer data);
+
+extern void
+on_clear_breakpoints_activate (GtkWidget *w, gpointer data);
+
+
+
+
+#endif /* MIXGTK_GEN_HANDLERS_H */
+
diff --git a/mixgtk/mixgtk_input.c b/mixgtk/mixgtk_input.c
new file mode 100644
index 0000000..fa98056
--- /dev/null
+++ b/mixgtk/mixgtk_input.c
@@ -0,0 +1,189 @@
+/* -*-c-*- -------------- mixgtk_input.c :
+ * Implementation of the functions declared in mixgtk_input.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/13 08:31:20 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include "mixgtk_widgets.h"
+#include "mixgtk_input.h"
+
+enum {
+ MSG_, SIGN_, B1_, B2_, B3_, B4_, B5_, DEC_, RESET_, OK_, SIZE_
+};
+
+static const gchar *WGT_NAMES_[SIZE_] = {
+ "word_label", "word_sign", "word_b1", "word_b2", "word_b3",
+ "word_b4", "word_b5", "word_decimal", "word_reset", "word_ok"
+};
+
+static GtkDialog *dialog_;
+static GtkWidget *childs_[SIZE_];
+static input_callback_t callback_;
+static gpointer data_;
+
+/* init */
+extern gboolean
+mixgtk_input_init (void)
+{
+ gint k;
+
+ dialog_ = GTK_DIALOG (mixgtk_widget_factory_get (MIXGTK_WIDGET_WORD_DIALOG));
+ g_return_val_if_fail (dialog_ != NULL, FALSE);
+ for (k = 0; k < SIZE_; ++k)
+ {
+ childs_[k] = mixgtk_widget_factory_get_by_name (WGT_NAMES_[k]);
+ g_return_val_if_fail (childs_[k] != NULL, FALSE);
+ }
+ return TRUE;
+
+}
+
+static void
+set_word_ (mix_word_t word)
+{
+ enum {SIZE = 50};
+ static gchar BUFFER[SIZE] = {0};
+ gint k;
+ gint val = mix_word_magnitude (word);
+ gboolean neg = mix_word_is_negative (word);
+ snprintf (BUFFER, SIZE, "%s%d", neg ? "-" : "", val);
+ gtk_entry_set_text (GTK_ENTRY (childs_[DEC_]), BUFFER);
+ gtk_entry_set_text (GTK_ENTRY (childs_[SIGN_]), neg ? "-" : "+");
+ for (k = 1; k < 6; ++k)
+ {
+ mix_byte_t b = mix_word_get_byte (word, k);
+ snprintf (BUFFER, SIZE, "%d", (int)b);
+ gtk_entry_set_text (GTK_ENTRY (childs_[SIGN_ + k]), BUFFER);
+ }
+}
+
+
+/* get a word */
+void
+mixgtk_input_word (const gchar *message, mix_word_t def,
+ input_callback_t cb, gpointer data)
+{
+ gtk_label_set_text (GTK_LABEL (childs_[MSG_]), message);
+ set_word_ (def);
+ callback_ = cb;
+ data_ = data;
+ gtk_widget_show (childs_[B1_]);
+ gtk_widget_show (childs_[B2_]);
+ gtk_widget_show (childs_[B3_]);
+ gtk_widget_show (GTK_WIDGET (dialog_));
+}
+
+/* get a short */
+void
+mixgtk_input_short (const gchar *message, mix_short_t def,
+ input_callback_t cb, gpointer data)
+{
+ gtk_label_set_text (GTK_LABEL (childs_[MSG_]), message);
+ set_word_ (mix_word_to_short_fast (def));
+ callback_ = cb;
+ data_ = data;
+ gtk_widget_show (GTK_WIDGET (dialog_));
+ gtk_widget_hide (childs_[B1_]);
+ gtk_widget_hide (childs_[B2_]);
+ gtk_widget_hide (childs_[B3_]);
+}
+
+#include <gdk/gdkkeysyms.h>
+
+/* dec and bytes input handler */
+gboolean
+on_word_dec_key_press (GtkWidget *dec, GdkEvent *event, gpointer *data)
+{
+ GdkEventKey *key = (GdkEventKey *)event;
+ if (key->string && strlen (key->string) > 0 && !iscntrl (key->string[0]))
+ {
+ gchar *text = gtk_entry_get_text (GTK_ENTRY (childs_[DEC_]));
+ gint val = atoi (text);
+ set_word_ (mix_word_new (val));
+ }
+ return FALSE;
+}
+
+gboolean
+on_word_byte_key_press (GtkWidget *widget, GdkEvent *event, gpointer *data)
+{
+ GdkEventKey *key = (GdkEventKey *)event;
+ if (key->string && strlen (key->string) > 0 && !iscntrl (key->string[0]))
+ {
+ mix_byte_t bytes[5];
+ gint k;
+ gchar *s;
+ mix_word_t w;
+
+ for (k = 0; k < 5; ++k)
+ {
+ gchar *text = gtk_entry_get_text (GTK_ENTRY (childs_[B1_ + k]));
+ bytes[k] = mix_byte_new (atoi (text));
+ }
+ w = mix_bytes_to_word (bytes, 5);
+ s = gtk_entry_get_text (GTK_ENTRY (childs_[SIGN_]));
+ if (s && s[0] == '-') mix_word_reverse_sign (w);
+ set_word_ (w);
+ }
+ return FALSE;
+}
+
+gboolean
+on_word_sign_key_press (GtkWidget *widget, GdkEvent *event, gpointer *data)
+{
+ GdkEventKey *key = (GdkEventKey *)event;
+ if (key->string && strlen (key->string) > 0 && !iscntrl (key->string[0]))
+ {
+ gchar s = key->string[0];
+ gchar *txt = gtk_entry_get_text (GTK_ENTRY (childs_[SIGN_]));
+ gchar c = txt ? txt[0] : '+';
+ if ( (s == '+' || s == '-') && s != c)
+ {
+ mix_word_t w =
+ mix_word_new (atoi
+ (gtk_entry_get_text (GTK_ENTRY (childs_[DEC_]))));
+ set_word_ (mix_word_negative (w));
+ }
+ }
+ return FALSE;
+}
+
+void
+on_word_ok_clicked (GtkWidget *widget, gpointer *data)
+{
+ const gchar *text = gtk_entry_get_text (GTK_ENTRY (childs_[DEC_]));
+ mix_word_t w = mix_word_new (atoi (text));
+ callback_ (w, data_);
+ gtk_widget_hide (GTK_WIDGET (dialog_));
+}
+
+void
+on_word_cancel_clicked (GtkWidget *widget, gpointer *data)
+{
+ gtk_widget_hide (GTK_WIDGET (dialog_));
+}
+
+void
+on_word_reset_clicked (GtkWidget *w, gpointer *data)
+{
+ set_word_ (MIX_WORD_ZERO);
+}
diff --git a/mixgtk/mixgtk_input.h b/mixgtk/mixgtk_input.h
new file mode 100644
index 0000000..275894d
--- /dev/null
+++ b/mixgtk/mixgtk_input.h
@@ -0,0 +1,49 @@
+/* -*-c-*- ---------------- mixgtk_input.h :
+ * Declaration of functions for user input
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/12 23:35:14 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_INPUT_H
+#define MIXGTK_INPUT_H
+
+#include <mixlib/mix_types.h>
+
+/* callback function type */
+typedef void (*input_callback_t)(mix_word_t result, gpointer data);
+
+/* init */
+extern gboolean
+mixgtk_input_init (void);
+
+/* get a word */
+extern void
+mixgtk_input_word (const gchar *message, mix_word_t def,
+ input_callback_t cb, gpointer data);
+
+/* get a short */
+extern void
+mixgtk_input_short (const gchar *message, mix_short_t def,
+ input_callback_t cb, gpointer data );
+
+
+#endif /* MIXGTK_INPUT_H */
+
diff --git a/mixgtk/mixgtk_mixal.c b/mixgtk/mixgtk_mixal.c
new file mode 100644
index 0000000..b59688d
--- /dev/null
+++ b/mixgtk/mixgtk_mixal.c
@@ -0,0 +1,213 @@
+/* -*-c-*- -------------- mixgtk_mixal.c :
+ * Implementation of the functions declared in mixgtk_mixal.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/12 23:48:29 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include <stdlib.h>
+#include "mixgtk_widgets.h"
+#include "mixgtk_mixal.h"
+
+
+static mix_vm_t *vm_;
+static GtkCList *clist_;
+static GdkColor sel_color_;
+static GdkColor break_color_;
+static GdkColor plain_color_;
+static gulong lineno_;
+
+#define SEL_COLOR_ "lightgrey"
+#define BREAK_COLOR_ "red"
+#define PLAIN_COLOR_ "white"
+
+static gboolean
+init_color_ (GdkColor *c, const gchar *name)
+{
+ static GdkColormap *cmap = NULL;
+ if (!cmap) cmap = gtk_widget_get_colormap (GTK_WIDGET (clist_));
+ return (gdk_color_parse (name, c) &&
+ gdk_colormap_alloc_color (cmap, c, FALSE, TRUE));
+}
+
+/* initialise the mixal widgets */
+gboolean
+mixgtk_mixal_init (mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, FALSE);
+ vm_ = vm;
+ clist_ = GTK_CLIST (mixgtk_widget_factory_get (MIXGTK_WIDGET_MIXAL));
+ g_return_val_if_fail (clist_ != NULL, FALSE);
+
+ /* allocate colors */
+ g_return_val_if_fail (init_color_ (&sel_color_, SEL_COLOR_), FALSE);
+ g_return_val_if_fail (init_color_ (&break_color_, BREAK_COLOR_), FALSE);
+ g_return_val_if_fail (init_color_ (&plain_color_, PLAIN_COLOR_), FALSE);
+
+ return TRUE;
+}
+
+/* load the corresponding mixal file */
+void
+mixgtk_mixal_load_file (void)
+{
+ enum {ADDR_SIZE = 20, CONT_SIZE = 200};
+ static gchar ADDR[ADDR_SIZE], CONT[CONT_SIZE];
+ static gchar *TEXT[] = {ADDR, CONT};
+ static gchar *NULL_TEXT[] = {NULL, NULL};
+
+ const mix_src_file_t *file;
+
+ g_assert (vm_);
+ g_assert (clist_);
+
+ gtk_clist_clear (clist_);
+
+ file = mix_vm_get_src_file (vm_);
+ if (file != NULL)
+ {
+ gint k;
+ mix_address_t addr;
+
+ lineno_ = mix_src_file_get_line_no (file);
+
+ gtk_clist_freeze (clist_);
+ for (k = 0; k < lineno_; ++k)
+ {
+ const gchar *line = mix_src_file_get_line (file, k + 1);
+ snprintf (CONT, CONT_SIZE, "%03d: %s", k + 1, line);
+ addr = mix_vm_get_lineno_address (vm_, k + 1);
+ if (addr != MIX_VM_CELL_NO)
+ {
+ sprintf (ADDR, "%04d: ", mix_short_magnitude (addr));
+ mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, addr),
+ ADDR + strlen (ADDR));
+ }
+ else
+ ADDR[0] = '\0';
+ gtk_clist_append (clist_, TEXT);
+ gtk_clist_set_row_data (clist_, k, GINT_TO_POINTER
+ (mix_short_magnitude (addr)));
+ }
+ gtk_clist_append (clist_, NULL_TEXT);
+ gtk_clist_set_row_data (clist_, k, GINT_TO_POINTER (MIX_VM_CELL_NO));
+ gtk_clist_unselect_row (clist_, 0, 0);
+ gtk_clist_thaw (clist_);
+ }
+ else
+ lineno_ = 0;
+}
+
+
+/* update the widgets */
+static void
+reset_bg_ (gint row)
+{
+ gint addr = GPOINTER_TO_INT (gtk_clist_get_row_data (clist_, row));
+ gboolean isset = mix_vm_has_breakpoint_at_address (vm_, addr);
+ gtk_clist_set_background (clist_, row,
+ isset ? &break_color_ : &plain_color_);
+}
+
+static void
+select_row_ (gint row)
+{
+ static gint last = -1;
+
+ gtk_clist_set_background (clist_, row, &sel_color_);
+ if (gtk_clist_row_is_visible (clist_, row) != GTK_VISIBILITY_FULL)
+ gtk_clist_moveto (clist_, row, 0, 0.25, 0);
+ if (last != -1 && last != row) reset_bg_ (last);
+ last = row;
+}
+
+void
+mixgtk_mixal_update (void)
+{
+ gint addr = 0;
+ gint k = 0;
+
+ g_assert (vm_);
+ g_assert (clist_);
+
+ addr = mix_short_magnitude (mix_vm_get_prog_count (vm_));
+ k = gtk_clist_find_row_from_data (clist_, GINT_TO_POINTER (addr));
+ select_row_ (k);
+}
+
+/* breakpoints */
+void
+mixgtk_mixal_update_bp_at_address (guint addr)
+{
+ gint k;
+
+ g_assert (vm_);
+ g_assert (clist_);
+
+ k = gtk_clist_find_row_from_data (clist_, GINT_TO_POINTER (addr));
+ reset_bg_ (k);
+}
+
+void
+mixgtk_mixal_update_bp_at_line (guint line)
+{
+ if ( line < 1 ) return;
+
+ while (line < lineno_)
+ {
+ gint addr = GPOINTER_TO_INT (gtk_clist_get_row_data (clist_, line - 1));
+ if (addr != MIX_VM_CELL_NO) break;
+ ++line;
+ }
+ reset_bg_ (line - 1);
+}
+
+void
+mixgtk_mixal_update_bp_all ()
+{
+ gint k, addr;
+ for (k = 0; k < lineno_; ++k) reset_bg_ (k);
+ addr = mix_vm_get_prog_count (vm_);
+ k = gtk_clist_find_row_from_data (clist_, GINT_TO_POINTER (addr));
+ select_row_ (k);
+}
+
+/* callbacks */
+void
+on_mixal_select_row (GtkWidget *w, gint row, gint col, GdkEventButton *e,
+ gpointer data)
+{
+ gboolean isset;
+ gint addr, pc;
+
+ gtk_clist_unselect_row (clist_, row, col);
+ addr = GPOINTER_TO_INT (gtk_clist_get_row_data (clist_, row));
+ pc = mix_vm_get_prog_count (vm_);
+ if (addr < MIX_VM_CELL_NO && addr != pc)
+ {
+ isset = mix_vm_has_breakpoint_at_address (vm_, addr);
+ if (isset)
+ mix_vm_clear_breakpoint_address (vm_, addr);
+ else
+ mix_vm_set_breakpoint_address (vm_, addr);
+ reset_bg_ (row);
+ }
+}
+
diff --git a/mixgtk/mixgtk_mixal.h b/mixgtk/mixgtk_mixal.h
new file mode 100644
index 0000000..819819a
--- /dev/null
+++ b/mixgtk/mixgtk_mixal.h
@@ -0,0 +1,60 @@
+/* -*-c-*- ---------------- mixgtk_mixal.h :
+ * Declarations for functions displaying the mixal source file
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/11 00:19:30 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_MIXAL_H
+#define MIXGTK_MIXAL_H
+
+#include <gtk/gtk.h>
+#include <mixlib/mix_vm.h>
+
+/* initialise the mixal widget */
+extern gboolean
+mixgtk_mixal_init (mix_vm_t *vm);
+
+/* load the corresponding mixal file */
+extern void
+mixgtk_mixal_load_file (void);
+
+/* update the widget */
+extern void
+mixgtk_mixal_update (void);
+
+/* breakpoints */
+extern void
+mixgtk_mixal_update_bp_at_address (guint addr);
+
+extern void
+mixgtk_mixal_update_bp_at_line (guint line);
+
+extern void
+mixgtk_mixal_update_bp_all (void);
+
+
+/* callbacks */
+extern void
+on_mixal_select_row (GtkWidget *w, gint row, gint col, GdkEventButton *e,
+ gpointer data);
+
+#endif /* MIXGTK_MIXAL_H */
+
diff --git a/mixgtk/mixgtk_mixvm.c b/mixgtk/mixgtk_mixvm.c
new file mode 100644
index 0000000..9c5d9bd
--- /dev/null
+++ b/mixgtk/mixgtk_mixvm.c
@@ -0,0 +1,423 @@
+/* -*-c-*- -------------- mixgtk_mixvm.c :
+ * Implementation of the functions declared in mixgtk_mixvm.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/14 16:34:31 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <mixlib/xmix_vm.h>
+#include "mixgtk_widgets.h"
+#include "mixgtk_mixvm.h"
+#include "mixgtk_cmd_dispatcher.h"
+#include "mixgtk_input.h"
+
+/* register widgets */
+#define REGISTER_NO_ (MIXGTK_WIDGET_rI6 - MIXGTK_WIDGET_rA + 1)
+
+static GtkEntry *reg_entries_[REGISTER_NO_];
+static GtkTooltips *tips_;
+static GtkEntry *loc_entry_;
+static GtkWidget *goto_;
+static GtkEntry *goto_entry_;
+static GtkToggleButton *over_button_;
+static GtkToggleButton *cmp_buttons_[3];
+static GtkCList *memory_;
+static GtkLabel *laptime_;
+static GtkLabel *progtime_;
+static GtkLabel *uptime_;
+static mix_vm_t *vm_;
+
+#define GOTO_ENTRY_NAME_ "goto_entry"
+
+static void
+update_register_ (mixgtk_widget_id_t reg)
+{
+ static gchar BUFFER[20];
+ mix_word_t tipval = MIX_WORD_ZERO;
+ switch (reg)
+ {
+ case MIXGTK_WIDGET_rA:
+ tipval = mix_vm_get_rA (vm_);
+ mix_word_print_to_buffer (tipval, BUFFER);
+ break;
+ case MIXGTK_WIDGET_rX:
+ tipval = mix_vm_get_rX (vm_);
+ mix_word_print_to_buffer (tipval, BUFFER);
+ break;
+ case MIXGTK_WIDGET_rJ:
+ tipval = mix_short_to_word_fast (mix_vm_get_rJ (vm_));
+ mix_short_print_to_buffer (mix_vm_get_rJ (vm_), BUFFER);
+ break;
+ case MIXGTK_WIDGET_rI1:
+ case MIXGTK_WIDGET_rI2:
+ case MIXGTK_WIDGET_rI3:
+ case MIXGTK_WIDGET_rI4:
+ case MIXGTK_WIDGET_rI5:
+ case MIXGTK_WIDGET_rI6:
+ {
+ gint k = reg - MIXGTK_WIDGET_rI1 + 1;
+ tipval = mix_short_to_word_fast (mix_vm_get_rI (vm_, k));
+ mix_short_print_to_buffer (mix_vm_get_rI (vm_, k), BUFFER);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ gtk_entry_set_text (reg_entries_[reg - MIXGTK_WIDGET_rA], BUFFER);
+ snprintf (BUFFER, 20, "%s%ld", mix_word_is_negative (tipval)? "-" : "",
+ mix_word_magnitude (tipval));
+ gtk_tooltips_set_tip (tips_,
+ GTK_WIDGET (reg_entries_[reg - MIXGTK_WIDGET_rA]),
+ BUFFER, NULL);
+
+}
+
+
+static void
+on_mem_adj_change_ (GtkAdjustment *adj)
+{
+ mixgtk_mixvm_update_cells ();
+}
+
+
+/* initialise the mixvm widgets */
+gboolean
+mixgtk_mixvm_init (mix_vm_t *vm)
+{
+ int k;
+ gchar *text[] = {"", ""};
+ GtkWidget *scrol;
+ GtkAdjustment *adj;
+
+ g_return_val_if_fail (vm != NULL, FALSE);
+ vm_ = vm;
+
+ tips_ = gtk_tooltips_new ();
+
+ for (k = 0; k < REGISTER_NO_; ++k)
+ {
+ reg_entries_[k] =
+ GTK_ENTRY (mixgtk_widget_factory_get (MIXGTK_WIDGET_rA + k));
+ g_return_val_if_fail (reg_entries_[k] != NULL, FALSE);
+ }
+
+ loc_entry_ = GTK_ENTRY (mixgtk_widget_factory_get (MIXGTK_WIDGET_LOC));
+ g_return_val_if_fail (loc_entry_ != NULL, FALSE);
+
+ uptime_ = GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_WIDGET_UPTIME));
+ g_return_val_if_fail (uptime_ != NULL, FALSE);
+
+ progtime_ = GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_WIDGET_PROGTIME));
+ g_return_val_if_fail (progtime_ != NULL, FALSE);
+
+ laptime_ = GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_WIDGET_LAPTIME));
+ g_return_val_if_fail (laptime_ != NULL, FALSE);
+
+ over_button_ =
+ GTK_TOGGLE_BUTTON (mixgtk_widget_factory_get (MIXGTK_WIDGET_OVER));
+ g_return_val_if_fail (over_button_ != NULL, FALSE);
+
+ for (k = 0; k < 3; ++k)
+ {
+ cmp_buttons_[k] =
+ GTK_TOGGLE_BUTTON (mixgtk_widget_factory_get (MIXGTK_WIDGET_CMP_L +k));
+ g_return_val_if_fail (cmp_buttons_[k] != NULL, FALSE);
+ }
+
+ memory_ = GTK_CLIST (mixgtk_widget_factory_get (MIXGTK_WIDGET_CELLS));
+ g_return_val_if_fail (memory_ != NULL, FALSE);
+ gtk_clist_set_column_justification (memory_, 0, GTK_JUSTIFY_CENTER);
+ gtk_clist_set_column_justification (memory_, 1, GTK_JUSTIFY_CENTER);
+ gtk_clist_freeze (memory_);
+ for (k = 0; k< MIX_VM_CELL_NO; ++k)
+ {
+ gchar buffer[20];
+ sprintf (buffer, "%04d", k);
+ text[0] = buffer;
+ gtk_clist_append (memory_, text);
+ }
+ gtk_clist_thaw (memory_);
+
+ scrol = mixgtk_widget_factory_get (MIXGTK_WIDGET_CELLS_SCROLL);
+ g_return_val_if_fail (scrol != NULL, FALSE);
+ adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrol));
+ gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
+ GTK_SIGNAL_FUNC (on_mem_adj_change_), NULL);
+
+ goto_ = mixgtk_widget_factory_get (MIXGTK_WIDGET_GOTO_DIALOG);
+ g_return_val_if_fail (goto_ != NULL, FALSE);
+
+ goto_entry_ = GTK_ENTRY (mixgtk_widget_factory_get_by_name
+ (GOTO_ENTRY_NAME_));
+ g_return_val_if_fail (goto_entry_ != NULL, FALSE);
+
+ mixgtk_mixvm_update_vm_widgets ();
+
+ return TRUE;
+}
+
+
+/* update register widgets */
+void
+mixgtk_mixvm_update_registers (void)
+{
+ gint k;
+ for (k = MIXGTK_WIDGET_rA; k <= MIXGTK_WIDGET_rI6; ++k)
+ update_register_ (k);
+}
+
+/* update the overflow toggle */
+void
+mixgtk_mixvm_update_over_toggle (void)
+{
+ g_assert (over_button_);
+ gtk_toggle_button_set_active (over_button_,
+ mix_vm_get_overflow (vm_));
+}
+
+/* update the comparison flag */
+void
+mixgtk_mixvm_update_cmp (void)
+{
+ gint toggle;
+
+ g_assert (cmp_buttons_);
+
+ toggle = mix_vm_get_cmpflag (vm_);
+ gtk_toggle_button_set_active (cmp_buttons_[toggle], TRUE);
+}
+
+
+/* update the memory cells */
+void
+mixgtk_mixvm_update_cells (void)
+{
+ static gchar BUFFER[20];
+ gint k = 0;
+
+ g_assert (memory_);
+
+ gtk_clist_freeze (memory_);
+
+ while (gtk_clist_row_is_visible (memory_, k) == GTK_VISIBILITY_NONE) ++k;
+ while (gtk_clist_row_is_visible (memory_, k) != GTK_VISIBILITY_NONE)
+ {
+ mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, k), BUFFER);
+ gtk_clist_set_text (memory_, k, 1, BUFFER);
+ ++k;
+ }
+
+ gtk_clist_thaw (memory_);
+}
+
+void
+mixgtk_mixvm_update_cells_to_address (gint address)
+{
+ g_assert (memory_);
+ g_return_if_fail (address < MIX_VM_CELL_NO);
+
+ gtk_clist_freeze (memory_);
+ gtk_clist_moveto (memory_, address, 0, 0, 0);
+ gtk_clist_thaw (memory_);
+ mixgtk_mixvm_update_cells ();
+}
+
+/* update the loc pointer */
+void
+mixgtk_mixvm_update_loc (void)
+{
+ enum {SIZE = 10 };
+ static gchar BUFFER[SIZE];
+ mix_short_t locval;
+
+ g_assert (loc_entry_);
+
+ locval = mix_vm_get_prog_count (vm_);
+ snprintf (BUFFER, SIZE, "%04d", mix_short_magnitude (locval));
+ gtk_entry_set_text (loc_entry_, BUFFER);
+}
+
+/* update times */
+void
+mixgtk_mixvm_update_times (void)
+{
+ enum {SIZE = 20 };
+ static gchar BUFFER[SIZE];
+ gint uptime, progtime, laptime;
+
+ g_assert (uptime_ && progtime_ && laptime_);
+ mixgtk_cmd_dispatcher_get_times (&uptime, &progtime, &laptime);
+ snprintf (BUFFER, SIZE, "%d", uptime);
+ gtk_label_set_text (uptime_, BUFFER);
+ snprintf (BUFFER, SIZE, "%d", progtime);
+ gtk_label_set_text (progtime_, BUFFER);
+ snprintf (BUFFER, SIZE, "%d", laptime);
+ gtk_label_set_text (laptime_, BUFFER);
+}
+
+
+/* update all mixvm widgets */
+void
+mixgtk_mixvm_update_vm_widgets (void)
+{
+ mixgtk_mixvm_update_registers ();
+ mixgtk_mixvm_update_loc ();
+ mixgtk_mixvm_update_over_toggle ();
+ mixgtk_mixvm_update_cmp ();
+ mixgtk_mixvm_update_cells ();
+ mixgtk_mixvm_update_times ();
+}
+
+
+/* update cmp flag */
+void
+on_cmp_e_toggled (GtkWidget *widget, gpointer data)
+{
+ if (GTK_TOGGLE_BUTTON (widget)->active)
+ mix_vm_set_cmpflag (vm_, mix_EQ);
+}
+
+void
+on_cmp_l_toggled (GtkWidget *widget, gpointer data)
+{
+ if (GTK_TOGGLE_BUTTON (widget)->active)
+ mix_vm_set_cmpflag (vm_, mix_LESS);
+}
+
+void
+on_cmp_g_toggled (GtkWidget *widget, gpointer data)
+{
+ if (GTK_TOGGLE_BUTTON (widget)->active)
+ mix_vm_set_cmpflag (vm_, mix_GREAT);
+}
+
+void
+on_overflow_toggled (GtkWidget *widget, gpointer data)
+{
+ mix_vm_set_overflow (vm_, GTK_TOGGLE_BUTTON (widget)->active);
+}
+
+
+void
+on_loc_arrow_clicked (GtkWidget *widget, gpointer data)
+{
+ gint address = mix_short_magnitude (mix_vm_get_prog_count (vm_));
+ mixgtk_mixvm_update_cells_to_address (address);
+}
+
+
+static void
+register_AX_ (mix_word_t w, gpointer reg)
+{
+ gint k = GPOINTER_TO_INT (reg);
+ if (k == 0)
+ mix_vm_set_rA (vm_, w);
+ else
+ mix_vm_set_rX (vm_, w);
+ update_register_ (MIXGTK_WIDGET_rA + k);
+}
+
+static void
+register_j_ (mix_word_t w, gpointer data)
+{
+ if (mix_word_is_negative (w)) mix_word_reverse_sign (w);
+ mix_vm_set_rJ (vm_, mix_word_to_short_fast (w));
+ update_register_ (MIXGTK_WIDGET_rJ);
+}
+
+static void
+register_i_ (mix_word_t w, gpointer reg)
+{
+ mix_vm_set_rI (vm_, GPOINTER_TO_INT (reg), mix_word_to_short_fast (w));
+ update_register_ (MIXGTK_WIDGET_rI1 - 1 + GPOINTER_TO_INT (reg));
+}
+
+gboolean
+on_register_click (GtkWidget *w, GdkEvent *e, gpointer data)
+{
+ enum {SIZE = 20};
+ static gchar BUFFER[SIZE];
+ gint k;
+
+ if (w == GTK_WIDGET (reg_entries_[0]))
+ mixgtk_input_word ("Register A", mix_vm_get_rA (vm_),
+ register_AX_, GINT_TO_POINTER (0));
+ else if (w == GTK_WIDGET (reg_entries_[1]))
+ mixgtk_input_word ("Register X", mix_vm_get_rX (vm_),
+ register_AX_, GINT_TO_POINTER(1));
+ else if (w == GTK_WIDGET (reg_entries_[2]))
+ mixgtk_input_short ("Register J", mix_vm_get_rJ (vm_), register_j_, NULL);
+ else for (k = 1; k < 7; ++k)
+ {
+ if (w == GTK_WIDGET (reg_entries_[2 + k]))
+ {
+ snprintf (BUFFER, SIZE, "Register I%d", k);
+ mixgtk_input_short (BUFFER, mix_vm_get_rI (vm_, k),
+ register_i_, GINT_TO_POINTER (k));
+ break;
+ }
+ }
+ return FALSE;
+}
+
+static void
+mem_cell_ (mix_word_t w, gpointer a)
+{
+ mix_short_t addr = mix_short_new (GPOINTER_TO_INT (a));
+ mix_vm_set_addr_contents (vm_, addr, w);
+ mixgtk_mixvm_update_cells ();
+}
+
+void
+on_memory_cells_select_row (GtkCList *w, gint row, gint col,
+ GdkEvent *e, gpointer data)
+{
+ enum {SIZE = 20};
+ static gchar BUFFER[SIZE];
+ snprintf (BUFFER, SIZE, "Memory cell no. %d", row);
+ mixgtk_input_word (BUFFER,
+ mix_vm_get_addr_contents (vm_, mix_short_new (row)),
+ mem_cell_, GINT_TO_POINTER (row));
+}
+
+void
+on_memory_cells_click_column (GtkCList *w, gint row, gpointer data)
+{
+ gtk_widget_show (goto_);
+}
+
+void
+on_goto_cancel_clicked (GtkWidget *w, gpointer data)
+{
+ gtk_widget_hide (goto_);
+}
+
+void
+on_goto_ok_clicked (GtkWidget *w, gpointer data)
+{
+ gchar *txt = gtk_entry_get_text (goto_entry_);
+ mix_short_t addr = mix_short_new (atoi (txt));
+ if (addr < MIX_VM_CELL_NO)
+ {
+ gtk_widget_hide (goto_);
+ mixgtk_mixvm_update_cells_to_address (addr);
+ }
+}
+
diff --git a/mixgtk/mixgtk_mixvm.h b/mixgtk/mixgtk_mixvm.h
new file mode 100644
index 0000000..8207d91
--- /dev/null
+++ b/mixgtk/mixgtk_mixvm.h
@@ -0,0 +1,84 @@
+/* -*-c-*- ---------------- mixgtk_mixvm.h :
+ * Functions dealing with the mixvm widgets
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/09 22:12:04 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_MIXVM_H
+#define MIXGTK_MIXVM_H
+
+#include <mixlib/mix_vm.h>
+
+/* initialise the mixvm widgets */
+extern gboolean
+mixgtk_mixvm_init (mix_vm_t *vm);
+
+/* update register widgets */
+extern void
+mixgtk_mixvm_update_registers (void);
+
+/* update the overflow toggle */
+extern void
+mixgtk_mixvm_update_over_toggle (void);
+
+/* update the comparison flag */
+extern void
+mixgtk_mixvm_update_cmp (void);
+
+/* update the memory cells */
+extern void
+mixgtk_mixvm_update_cells (void);
+
+extern void
+mixgtk_mixvm_update_cells_to_address (gint address);
+
+/* update the loc pointer */
+extern void
+mixgtk_mixvm_update_loc (void);
+
+/* update times */
+extern void
+mixgtk_mixvm_update_times (void);
+
+/* update all mixvm widgets */
+extern void
+mixgtk_mixvm_update_vm_widgets (void);
+
+/* callbacks */
+extern void
+on_cmp_e_toggled (GtkWidget *widget, gpointer data);
+
+extern void
+on_cmp_g_toggled (GtkWidget *widget, gpointer data);
+
+extern void
+on_cmp_l_toggled (GtkWidget *widget, gpointer data);
+
+extern void
+on_overflow_toggled (GtkWidget *widget, gpointer data);
+
+extern void
+on_loc_arrow_clicked (GtkWidget *widget, gpointer data);
+
+
+
+#endif /* MIXGTK_MIXVM_H */
+
diff --git a/mixgtk/mixgtk_widgets.c b/mixgtk/mixgtk_widgets.c
new file mode 100644
index 0000000..165da81
--- /dev/null
+++ b/mixgtk/mixgtk_widgets.c
@@ -0,0 +1,112 @@
+/* -*-c-*- -------------- mixgtk_widgets.c :
+ * Implementation of the functions declared in mixgtk_widgets.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/15 14:42:37 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+
+#include <glade/glade.h>
+#include <mixlib/mix.h>
+#include "mixgtk_widgets.h"
+
+/* the glade spec */
+static GladeXML *xml_ = NULL;
+
+/* widget names */
+static const gchar *names_[] = {
+ "main_window",
+ "main_statusbar",
+ "word_dialog",
+ "about_dialog",
+ "goto_dialog",
+ "command_prompt",
+ "command_log",
+ "mixal_clist",
+ "rA_entry",
+ "rX_entry",
+ "rJ_entry",
+ "rI1_entry",
+ "rI2_entry",
+ "rI3_entry",
+ "rI4_entry",
+ "rI5_entry",
+ "rI6_entry",
+ "lesser_radio",
+ "equal_radio",
+ "greater_radio",
+ "over_toggle",
+ "memory_cells",
+ "memory_scroll",
+ "devices_notebook",
+ "loc_entry",
+ "elapsed_label",
+ "program_label",
+ "uptime_label",
+ NULL
+};
+
+#define WIDGET_NO_ (sizeof (names_) / sizeof (names_[0]))
+
+#define VERSION_LABEL_ "version_label"
+#define GPL_TEXT_ "gpl_text"
+
+GtkWidget *about_;
+
+/* create a new factory from an xml glade file */
+gboolean
+mixgtk_widget_factory_init (const char *glade_file)
+{
+ GtkWidget *label;
+ glade_init ();
+ xml_ = glade_xml_new (glade_file, NULL);
+ if (!xml_) return FALSE;
+ glade_xml_signal_autoconnect (xml_);
+
+ about_ = mixgtk_widget_factory_get (MIXGTK_WIDGET_ABOUT_DIALOG);
+ g_return_val_if_fail (about_ != NULL, FALSE);
+ label = mixgtk_widget_factory_get_by_name (VERSION_LABEL_);
+ g_return_val_if_fail (label != NULL, FALSE);
+ gtk_label_set_text (GTK_LABEL(label), VERSION);
+ gtk_widget_show (label);
+ return TRUE;
+}
+
+/* get a widget */
+GtkWidget *
+mixgtk_widget_factory_get (mixgtk_widget_id_t widget)
+{
+ g_return_val_if_fail (widget < WIDGET_NO_, NULL);
+ return glade_xml_get_widget (xml_, names_[widget]);
+}
+
+/* Get a widget by name */
+GtkWidget *
+mixgtk_widget_factory_get_by_name (const gchar *name)
+{
+ return glade_xml_get_widget (xml_, name);
+}
+
+/* about box */
+void
+on_about_activate (GtkWidget *w, gpointer data)
+{
+ gtk_widget_show (about_);
+}
diff --git a/mixgtk/mixgtk_widgets.h b/mixgtk/mixgtk_widgets.h
new file mode 100644
index 0000000..f20ddc3
--- /dev/null
+++ b/mixgtk/mixgtk_widgets.h
@@ -0,0 +1,80 @@
+/* -*-c-*- ---------------- mixgtk_widgets.h :
+ * glade-based factory of mixvm widgets
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/15 14:42:13 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXGTK_WIDGETS_H
+#define MIXGTK_WIDGETS_H
+
+#include <gtk/gtk.h>
+#include <mixlib/mix_vm.h>
+
+/* enumeration of mixvm widget ids */
+typedef enum {
+ MIXGTK_WIDGET_MAIN, /* main app window */
+ MIXGTK_WIDGET_STATUSBAR,
+ MIXGTK_WIDGET_WORD_DIALOG, /* input dialog for a mix word */
+ MIXGTK_WIDGET_ABOUT_DIALOG,
+ MIXGTK_WIDGET_GOTO_DIALOG,
+ MIXGTK_WIDGET_PROMPT, /* command prompt */
+ MIXGTK_WIDGET_LOG, /* command output */
+ MIXGTK_WIDGET_MIXAL, /* mixal source file */
+ MIXGTK_WIDGET_rA,
+ MIXGTK_WIDGET_rX,
+ MIXGTK_WIDGET_rJ,
+ MIXGTK_WIDGET_rI1,
+ MIXGTK_WIDGET_rI2,
+ MIXGTK_WIDGET_rI3,
+ MIXGTK_WIDGET_rI4,
+ MIXGTK_WIDGET_rI5,
+ MIXGTK_WIDGET_rI6,
+ MIXGTK_WIDGET_CMP_L,
+ MIXGTK_WIDGET_CMP_E,
+ MIXGTK_WIDGET_CMP_G,
+ MIXGTK_WIDGET_OVER,
+ MIXGTK_WIDGET_CELLS,
+ MIXGTK_WIDGET_CELLS_SCROLL,
+ MIXGTK_WIDGET_DEVICE,
+ MIXGTK_WIDGET_LOC,
+ MIXGTK_WIDGET_LAPTIME,
+ MIXGTK_WIDGET_PROGTIME,
+ MIXGTK_WIDGET_UPTIME,
+ MIXGTK_WIDGET_NONE
+} mixgtk_widget_id_t;
+
+
+/* create a new factory from an xml glade file */
+extern gboolean
+mixgtk_widget_factory_init (const char *glade_file);
+
+
+/* get a widget */
+extern GtkWidget *
+mixgtk_widget_factory_get (mixgtk_widget_id_t widget);
+
+/* Get a widget by name */
+extern GtkWidget *
+mixgtk_widget_factory_get_by_name (const gchar *name);
+
+
+#endif /* MIXGTK_WIDGETS_H */
+
diff --git a/mixlib/.cvsignore b/mixlib/.cvsignore
new file mode 100644
index 0000000..71b540f
--- /dev/null
+++ b/mixlib/.cvsignore
@@ -0,0 +1,7 @@
+
+.deps
+Makefile
+Makefile.in
+lex.yy.c
+mix_eval_scanner.c
+mix_scanner.c
diff --git a/mixlib/Makefile.am b/mixlib/Makefile.am
new file mode 100644
index 0000000..5091e88
--- /dev/null
+++ b/mixlib/Makefile.am
@@ -0,0 +1,33 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2000 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+SUBDIRS = testsuite
+INCLUDES = -I$(includedir) -DG_LOG_DOMAIN=\"libmix\"
+
+noinst_LIBRARIES = libmix.a
+libmix_a_SOURCES = mix.h mix.c \
+ mix_types.h mix_types.c \
+ mix_ins.h mix_ins.c \
+ mix_vm.h mix_vm.c xmix_vm.h xmix_vm.c \
+ mix_vm_dump.h mix_vm_dump.c \
+ mix_io.h mix_io.c xmix_io.h xmix_io.c \
+ mix_symbol_table.h mix_symbol_table.c \
+ mix_file.h mix_file.c \
+ mix_code_file.h mix_code_file.c \
+ mix_parser.h xmix_parser.h mix_parser.c mix_scanner.l \
+ mix_device.h mix_device.c xmix_device.h xmix_device.c \
+ mix_eval.h mix_eval.c xmix_eval.h mix_eval_scanner.l \
+ mix_src_file.c mix_src_file.h \
+ mix_vm_clock.c mix_vm_clock.h \
+ mix_vm_command.c mix_vm_command.h
+
+
diff --git a/mixlib/mix.c b/mixlib/mix.c
new file mode 100644
index 0000000..305bb65
--- /dev/null
+++ b/mixlib/mix.c
@@ -0,0 +1,63 @@
+/* -*-c-*- -------------- mix.c :
+ * Implementation of the functions declared in mix.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "mix_types.h"
+#include "mix_ins.h"
+#include "mix_code_file.h"
+#include "mix.h"
+
+
+/* This function must be called before using the library */
+void
+mix_init_lib(void)
+{
+ mix_init_types ();
+ mix_init_ins ();
+ mix_code_file_set_defext (MIX_CODE_DEFEXT);
+}
+
+
+/* This function must be called for deallocating the lib resources
+ when it is no longer in use
+*/
+void
+mix_release_lib (void)
+{
+ /* clean the user defined code file extension (if any) */
+ mix_code_file_set_defext (NULL);
+ mix_release_ins ();
+}
+
+const char *MIX_GPL_LICENSE =
+"Copyright (C) 2000, 2001 Free Software Foundation, Inc.\n"
+"GNU MDK is free software; you can redistribute it and/or modify\n"
+"it under the terms of the GNU General Public License as published by\n"
+"the Free Software Foundation; either version 2 of the License, or\n"
+"(at your option) any later version.\n"
+"GNU MDK is distributed in the hope that it will be useful,\n"
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+"GNU General Public License for more details.\n"
+"You should have received a copy of the GNU General Public License\n"
+"along with this program; if not, write to the Free Software\n"
+"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n";
+
diff --git a/mixlib/mix.h b/mixlib/mix.h
new file mode 100644
index 0000000..42eb4c9
--- /dev/null
+++ b/mixlib/mix.h
@@ -0,0 +1,65 @@
+/* -*-c-*- ---------------- mix.h :
+ * Initialisation of the mix library
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_H
+#define MIX_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#else
+# warning "config.h not found, package misconfigured."
+# define PACKAGE "mdk"
+# define VERSION "0.0"
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_GETTEXT
+# include <libintl.h>
+# define gettext_noop(String) (String)
+#else
+# include <intl/libintl.h>
+#endif
+
+#define _(String) gettext (String)
+#define N_(String) gettext_noop (String)
+
+#include <glib.h>
+
+/* This function must be called before using the library */
+extern void
+mix_init_lib (void);
+
+/* This function must be called for deallocating the lib resources
+ when it is no longer in use
+*/
+extern void
+mix_release_lib (void);
+
+
+extern const char *MIX_GPL_LICENSE;
+
+
+#endif /* MIX_H */
+
diff --git a/mixlib/mix_code_file.c b/mixlib/mix_code_file.c
new file mode 100644
index 0000000..604f3cd
--- /dev/null
+++ b/mixlib/mix_code_file.c
@@ -0,0 +1,326 @@
+/* -*-c-*- -------------- mix_code_file.c :
+ * Implementation of the functions declared in mix_code_file.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "mix.h"
+#include "xmix_io.h"
+#include "mix_code_file.h"
+
+/* mix_code_file_t type */
+static const gint32 SIGNATURE_ = 0xDEADBEEF; /* release files */
+static const gint32 SIGNATURE_D_ = 0xBEEFDEAD; /* debug files */
+
+#define IS_DEBUG_(file) ((file)->header.signature == SIGNATURE_D_)
+#define IS_RELEASE_(file) ((file)->header.signature == SIGNATURE_)
+
+
+typedef struct mix_cfheader_t mix_cfheader_t;
+struct mix_cfheader_t
+{
+ gint32 signature;
+ gint mj_ver;
+ gint mn_ver;
+ gint16 start;
+ size_t path_len;
+};
+
+struct mix_code_file_t
+{
+ mix_file_t *file; /* the underlying disk file */
+ mix_address_t address; /* current address while reading */
+ mix_cfheader_t header; /* file header */
+ gchar *source_path; /* variable length part of the header*/
+ mix_symbol_table_t *symbol_table; /* code files with debug info fill it*/
+};
+
+#define to_io_(cf) MIX_IOCHANNEL (cf->file)
+
+/* Code files are lists of tagged words. A MIX_INS_TAG_ denotes
+ * that the word is an instruction, whose address is the next to
+ * the previous instruction's one, while a MIX_ADDR_TAG_ indicates
+ * that the word is a new address origin for the next instructions.
+ * The tags are stored as bit patterns in bit 31 of the mix word.
+ */
+#define MIX_ADDR_TAG_ (MIX_WORD_SIGN_BIT<<1)
+
+#define is_ins_(word) (((word)&MIX_ADDR_TAG_) == MIX_WORD_ZERO)
+#define is_addr_(word) (((word)&MIX_ADDR_TAG_) == MIX_ADDR_TAG_)
+#define tag_ins_(word) (word)
+#define tag_addr_(word) ((word)|MIX_ADDR_TAG_)
+#define extract_ins_(tagged) (tagged)
+#define extract_addr_(tagged) ((tagged)&MIX_SHORT_MAX)
+
+/* mix code files have a default extension (.mix) which is customizable */
+static const gchar *DEFEXT_ = NULL;
+
+const gchar *
+mix_code_file_get_defext (void)
+{
+ return DEFEXT_;
+}
+
+gboolean
+mix_code_file_set_defext (const gchar *ext)
+{
+ if (DEFEXT_ != NULL) g_free ((void *)DEFEXT_);
+ DEFEXT_ = (ext != NULL)? g_strdup (ext):NULL;
+ return (DEFEXT_ != NULL || ext == NULL);
+}
+
+/* create/destroy code files for read or write */
+static mix_code_file_t *
+mix_code_file_new_ (const gchar *name, mix_fmode_t mode)
+{
+ mix_code_file_t *result = g_new (mix_code_file_t, 1);
+ if ( result != NULL )
+ {
+ result->file = mix_file_new_with_def_ext (name, mode, DEFEXT_);
+ result->address = MIX_SHORT_ZERO;
+ result->symbol_table = NULL;
+ }
+ if ( result != NULL && result->file == NULL )
+ {
+ g_free (result);
+ result = NULL;
+ }
+ return result;
+}
+
+mix_code_file_t *
+mix_code_file_new_read (const gchar *name)
+{
+ mix_code_file_t *result = mix_code_file_new_ (name, mix_io_READ);
+ mix_cfheader_t *header;
+ FILE *file;
+ gboolean check;
+
+ if ( result == NULL )
+ return NULL;
+
+ file = mix_file_to_FILE (result->file);
+ header = &(result->header);
+ check = fread (header, sizeof (mix_cfheader_t), 1, file);
+
+ if ( check )
+ check = IS_RELEASE_ (result) || IS_DEBUG_ (result);
+ if ( check )
+ {/* a code file is compatible if its major version is
+ is the same as this package's and its minor version is <= */
+ gint major, minor;
+ sscanf (VERSION, "%d.%d", &major, &minor);
+ check = header->mj_ver == major && header->mn_ver <= minor;
+ }
+ if ( check )
+ {/* get source path */
+ result->source_path = g_strnfill (1 + header->path_len, '\0');
+ check = result->source_path != NULL
+ && fgets (result->source_path, 1 + header->path_len, file) != NULL;
+ }
+ if ( check && IS_DEBUG_ (result) )
+ {/* read symbol table */
+ result->symbol_table = mix_symbol_table_new_from_file (file);
+ check = result->symbol_table != NULL;
+ }
+ if ( !check )
+ {
+ mix_code_file_delete (result);
+ return NULL;
+ }
+ return result;
+}
+
+mix_code_file_t *
+mix_code_file_new_write(const gchar *name, mix_address_t addr,
+ const gchar *source_path, gboolean debug,
+ const mix_symbol_table_t *table)
+{
+ mix_code_file_t *result;
+ FILE *file;
+ gboolean check;
+
+ result = mix_code_file_new_ (name, mix_io_WRITE);
+ if ( result == NULL || ( file = mix_file_to_FILE (result->file) ) == NULL )
+ return NULL;
+ else if ( source_path != NULL )
+ {
+ result->source_path = g_strdup (source_path/*, MAX_PATH_LEN_*/);
+ if ( result->source_path == NULL )
+ {
+ mix_code_file_delete (result);
+ return NULL;
+ }
+ }
+ else
+ result->source_path = NULL;
+
+ result->header.signature = debug? SIGNATURE_D_:SIGNATURE_;
+ sscanf (VERSION, "%d.%d", &result->header.mj_ver, &result->header.mn_ver);
+ result->header.start = (gint16) addr;
+ result->header.path_len = strlen (result->source_path);
+ check = write_data_ (to_io_ (result), &result->header, 1);
+ if ( check && result->source_path != NULL )
+ check = fputs (result->source_path, file) != EOF;
+ if ( check && debug )
+ mix_symbol_table_print (table, MIX_SYM_LINE, file, TRUE);
+ if ( !check )
+ {
+ mix_code_file_delete (result);
+ return NULL;
+ }
+ return result;
+}
+
+void
+mix_code_file_delete (mix_code_file_t *file)
+{
+ g_return_if_fail (file != NULL);
+ mix_file_delete (file->file);
+ if ( file->source_path ) g_free (file->source_path);
+ g_free (file);
+}
+
+
+
+/* get general parameters from a code file */
+gboolean
+mix_code_file_is_debug (const mix_code_file_t *file)
+{
+ return (file == NULL ) ? FALSE : IS_DEBUG_ (file);
+}
+
+
+gint
+mix_code_file_major_version (const mix_code_file_t *file)
+{
+ g_return_val_if_fail (file != NULL, 0);
+ return file->header.mj_ver;
+}
+
+gint
+mix_code_file_minor_version (const mix_code_file_t *file)
+{
+ g_return_val_if_fail (file != NULL, 0);
+ return file->header.mn_ver;
+}
+
+mix_address_t
+mix_code_file_get_start_addr (const mix_code_file_t *file)
+{
+ g_return_val_if_fail (file != NULL, MIX_SHORT_ZERO);
+ return mix_short_new (file->header.start);
+}
+
+mix_symbol_table_t *
+mix_code_file_get_symbol_table(mix_code_file_t *file)
+{
+ mix_symbol_table_t *result = NULL;
+ g_return_val_if_fail (file != NULL, NULL);
+ result = file->symbol_table;
+ file->symbol_table = NULL;
+ return result;
+}
+
+/* read instructions from a code file */
+gboolean
+mix_code_file_is_eof (mix_code_file_t *file)
+{
+ return is_eof_ (to_io_ (file));
+}
+
+gboolean
+mix_code_file_get_ins (mix_code_file_t *file, mix_ins_desc_t *desc)
+{
+ mix_word_t next;
+ g_return_val_if_fail (file != NULL, FALSE);
+ g_return_val_if_fail (desc != NULL, FALSE);
+ while (TRUE)
+ {
+ if ( ! mix_io_read_word_array (to_io_ (file), &next, 1) ) return FALSE;
+ if ( is_addr_ (next) )
+ file->address = extract_addr_ (next);
+ else if ( is_ins_ (next) )
+ {
+ desc->ins = extract_ins_ (next);
+ desc->address = (file->address)++;
+ if ( IS_DEBUG_ (file) )
+ {
+ mix_short_t lineno;
+ if ( !mix_io_read_short_array (to_io_ (file), &lineno, 1) )
+ return FALSE;
+ desc->lineno = mix_short_magnitude (lineno);
+ }
+ else
+ desc->lineno = 0;
+ return TRUE;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ return FALSE;
+ }
+ };
+}
+
+/* Write instructions to a code file */
+gboolean
+mix_code_file_write_ins (mix_code_file_t *file, const mix_ins_desc_t *desc)
+{
+ g_return_val_if_fail (desc != NULL, FALSE);
+ return ( mix_code_file_set_address (file, desc->address) &&
+ mix_code_file_write_next_ins (file, desc->ins, desc->lineno) );
+}
+
+gboolean
+mix_code_file_write_next_ins (mix_code_file_t *file, mix_word_t ins,
+ guint lineno)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+ if ( mix_io_write_word (to_io_ (file), tag_ins_ (ins))
+ && ( IS_RELEASE_ (file)
+ || mix_io_write_short (to_io_ (file), mix_short_new (lineno)) )
+ )
+ {
+ ++(file->address);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+gboolean
+mix_code_file_set_address (mix_code_file_t *file, mix_address_t address)
+{
+ g_return_val_if_fail(file != NULL, FALSE);
+ if ( file->address != address ) {
+ if ( !mix_io_write_word (to_io_ (file),
+ tag_addr_ (mix_short_to_word_fast (address))) )
+ return FALSE;
+ file->address = address;
+ }
+ return TRUE;
+}
+
+/* get details about the source file */
+const gchar *
+mix_code_file_get_source_path (const mix_code_file_t *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+ return file->source_path;
+}
diff --git a/mixlib/mix_code_file.h b/mixlib/mix_code_file.h
new file mode 100644
index 0000000..0678910
--- /dev/null
+++ b/mixlib/mix_code_file.h
@@ -0,0 +1,106 @@
+/* -*-c-*- ---------------- mix_code_file.h :
+ * Declaration of mix_code_file_t, a file containing compiled mix
+ * instructions.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_CODE_FILE_H
+#define MIX_CODE_FILE_H
+
+#include "mix_file.h"
+#include "mix_ins.h"
+#include "mix_symbol_table.h"
+
+/* mix_code_file_t type */
+typedef struct mix_code_file_t mix_code_file_t;
+
+/* instructions are loaded at specific memory addresses and related to
+ source line numbers
+*/
+typedef struct mix_ins_desc_t mix_ins_desc_t;
+struct mix_ins_desc_t
+{
+ mix_word_t ins; /* a mix instruction coded into a word */
+ mix_address_t address; /* the address of this instruction */
+ guint lineno; /* source file line no. */
+};
+
+/* mix code files have a default extension (.mix) which is customizable */
+extern const gchar *
+mix_code_file_get_defext(void);
+
+extern gboolean
+mix_code_file_set_defext(const gchar *ext);
+
+/* create/destroy code files for read or write */
+/* if -name- does not end with defext, it is automatically appended */
+extern mix_code_file_t *
+mix_code_file_new_read(const gchar *name);
+
+/* open a code file for write with/out debug information */
+extern mix_code_file_t *
+mix_code_file_new_write(const gchar *name, mix_address_t start,
+ const gchar *source_path, gboolean debug,
+ const mix_symbol_table_t *table);
+
+extern void
+mix_code_file_delete(mix_code_file_t *file);
+
+/* get general parameters from a code file */
+extern gboolean
+mix_code_file_is_debug(const mix_code_file_t *file);
+
+extern gint
+mix_code_file_major_version(const mix_code_file_t *file);
+
+extern gint
+mix_code_file_minor_version(const mix_code_file_t *file);
+
+extern mix_address_t
+mix_code_file_get_start_addr(const mix_code_file_t *file);
+
+extern mix_symbol_table_t *
+mix_code_file_get_symbol_table(mix_code_file_t *file);
+
+/* read instructions from a code file */
+extern gboolean
+mix_code_file_is_eof(mix_code_file_t *file);
+
+extern gboolean
+mix_code_file_get_ins(mix_code_file_t *file, mix_ins_desc_t *desc);
+
+/* write instructions to a code file */
+extern gboolean
+mix_code_file_write_ins(mix_code_file_t *file, const mix_ins_desc_t *desc);
+
+extern gboolean
+mix_code_file_write_next_ins(mix_code_file_t *file, mix_word_t ins,
+ guint lineno);
+
+extern gboolean
+mix_code_file_set_address(mix_code_file_t *file, mix_address_t address);
+
+/* get details about the source file */
+extern const gchar *
+mix_code_file_get_source_path (const mix_code_file_t *file);
+
+
+#endif /* MIX_CODE_FILE_H */
+
diff --git a/mixlib/mix_device.c b/mixlib/mix_device.c
new file mode 100644
index 0000000..13e7150
--- /dev/null
+++ b/mixlib/mix_device.c
@@ -0,0 +1,163 @@
+/* -*-c-*- -------------- mix_device.c :
+ * Implementation of the functions declared in mix_device.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "mix_file.h"
+#include "xmix_device.h"
+
+mix_device_t *
+mix_device_new (mix_device_type_t type)
+{
+ mix_device_t *result = NULL;
+ g_return_val_if_fail (type < mix_dev_INVALID, NULL);
+ result = g_new (mix_device_t, 1);
+ result->type = type;
+ if (type != mix_dev_CONSOLE) {
+ result->file = MIX_IOCHANNEL(mix_file_new_with_def_ext (DEF_NAMES_[type],
+ FMODES_[type],
+ DEV_EXT_));
+ } else
+ result->file = mix_io_new (stdout);
+ result->vtable = DEF_DEV_VTABLE_;
+ return result;
+}
+
+
+
+mix_device_t *
+mix_device_new_with_name (mix_device_type_t type, const gchar *name)
+{
+ mix_device_t *result = NULL;
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (type < mix_dev_INVALID, NULL);
+ result = g_new (mix_device_t, 1);
+ result->type = type;
+ if (type != mix_dev_CONSOLE)
+ {
+ result->file = MIX_IOCHANNEL(mix_file_new_with_def_ext (name,
+ FMODES_[type],
+ DEV_EXT_));
+ }
+ else
+ {
+ result->file = mix_io_new (stdout);
+ }
+ result->vtable = DEF_DEV_VTABLE_;
+ return result;
+}
+
+/*
+ Create a new device with a given type and stream
+*/
+mix_device_t *
+mix_device_new_with_file (mix_device_type_t type, FILE *file)
+{
+ mix_device_t *result = NULL;
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (type < mix_dev_INVALID, NULL);
+ result = g_new (mix_device_t, 1);
+ result->type = type;
+ result->file = mix_io_new (file);
+ result->vtable = DEF_DEV_VTABLE_;
+ return result;
+}
+
+void
+mix_device_delete (mix_device_t *dev)
+{
+ if (dev != NULL)
+ {
+ if (dev->type != mix_dev_CONSOLE && GET_FILE_(dev) != NULL)
+ mix_file_delete (GET_FILE_(dev));
+ g_free (dev);
+ }
+}
+
+mix_device_type_t
+mix_device_type (const mix_device_t *dev)
+{
+ g_return_val_if_fail (dev != NULL, mix_dev_INVALID);
+ return dev->type;
+}
+
+const char *
+mix_device_get_name (const mix_device_t *dev)
+{
+ g_return_val_if_fail (dev != NULL, NULL);
+ return mix_file_base_name(GET_FILE_(dev));
+}
+
+/*
+ Get the device block size
+*/
+size_t
+mix_device_block_size (const mix_device_t *dev)
+{
+ g_return_val_if_fail (dev != NULL, 0);
+ return SIZES_[dev->type];
+}
+
+/*
+ Get the device io mode
+*/
+mix_device_mode_t
+mix_device_mode (const mix_device_t *dev)
+{
+ g_return_val_if_fail (dev != NULL, 0);
+ return MODES_[dev->type];
+}
+
+/*
+ Write a block to the device.
+*/
+gboolean
+mix_device_write (mix_device_t *dev, const mix_word_t *block)
+{
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (block != NULL, FALSE);
+ g_assert (dev->vtable != NULL);
+ return (dev->vtable->write) (dev, block);
+}
+
+gboolean
+mix_device_read (mix_device_t *dev, mix_word_t *block)
+{
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (block != NULL, FALSE);
+ g_assert (dev->vtable != NULL);
+ return (dev->vtable->read) (dev, block);
+}
+
+gboolean
+mix_device_ioc (mix_device_t *dev, mix_short_t arg)
+{
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_assert (dev->vtable != NULL);
+ return (dev->vtable->ioc) (dev, arg);
+}
+
+gboolean
+mix_device_busy (const mix_device_t *dev)
+{
+ g_return_val_if_fail (dev != NULL, FALSE);
+ return (dev->vtable->busy) (dev);
+
+}
diff --git a/mixlib/mix_device.h b/mixlib/mix_device.h
new file mode 100644
index 0000000..7248d72
--- /dev/null
+++ b/mixlib/mix_device.h
@@ -0,0 +1,151 @@
+/* -*-c-*- ---------------- mix_device.h :
+ * Declaration of mix_device_t and associated methods.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_DEVICE_H
+#define MIX_DEVICE_H
+
+#include <stddef.h>
+#include <stdio.h>
+#include "mix.h"
+#include "mix_types.h"
+
+/*
+ A mix device, which derives from mix_io_channel_t
+*/
+typedef struct mix_device_t mix_device_t;
+
+/*
+ The device type
+*/
+typedef enum {
+ mix_dev_TAPE_0,
+ mix_dev_TAPE_1,
+ mix_dev_TAPE_2,
+ mix_dev_TAPE_3,
+ mix_dev_TAPE_4,
+ mix_dev_TAPE_5,
+ mix_dev_TAPE_6,
+ mix_dev_TAPE_7,
+ mix_dev_DISK_0,
+ mix_dev_DISK_1,
+ mix_dev_DISK_2,
+ mix_dev_DISK_3,
+ mix_dev_DISK_4,
+ mix_dev_DISK_5,
+ mix_dev_DISK_6,
+ mix_dev_DISK_7,
+ mix_dev_CARD_RD,
+ mix_dev_CARD_WR,
+ mix_dev_PRINTER,
+ mix_dev_CONSOLE,
+ mix_dev_PAPER_TAPE,
+ mix_dev_INVALID
+} mix_device_type_t;
+
+/*
+ The device io mode
+*/
+typedef enum {
+ mix_dev_BIN,
+ mix_dev_CHAR
+} mix_device_mode_t;
+
+/*
+ Create a new device with default name and given type.
+*/
+extern mix_device_t *
+mix_device_new (mix_device_type_t type);
+
+/*
+ Create a new device with a given type and name.
+*/
+extern mix_device_t *
+mix_device_new_with_name (mix_device_type_t type, const gchar *name);
+
+/*
+ Create a new device with a given type and stream
+*/
+extern mix_device_t *
+mix_device_new_with_file (mix_device_type_t type, FILE *file);
+
+/*
+ Delete a device.
+*/
+extern void
+mix_device_delete(mix_device_t *dev);
+
+
+/*
+ Get a device type
+*/
+extern mix_device_type_t
+mix_device_type (const mix_device_t *dev);
+
+
+/*
+ Get a device name
+*/
+extern const char *
+mix_device_get_name (const mix_device_t *dev);
+
+/*
+ Get the device block size
+*/
+extern size_t
+mix_device_block_size (const mix_device_t *dev);
+
+/*
+ Get the device io mode
+*/
+extern mix_device_mode_t
+mix_device_mode (const mix_device_t *dev);
+
+/*
+ Write a block to the device.
+*/
+extern gboolean
+mix_device_write (mix_device_t *dev, const mix_word_t *block);
+
+/*
+ Read a block from the device.
+*/
+extern gboolean
+mix_device_read (mix_device_t *dev, mix_word_t *block);
+
+/*
+ Perform an io control operation on the device.
+ The parameter _arg_ is the operation's argument:
+ 0- rewind to beginning
+ <0 - rewind the given number of blocks
+ >0 - skip forward the given number of blocks
+*/
+extern gboolean
+mix_device_ioc (mix_device_t *dev, mix_short_t arg);
+
+/*
+ Check if a device is busy
+*/
+extern gboolean
+mix_device_busy (const mix_device_t *dev);
+
+#endif /* MIX_DEVICE_H */
+
diff --git a/mixlib/mix_eval.c b/mixlib/mix_eval.c
new file mode 100644
index 0000000..b629852
--- /dev/null
+++ b/mixlib/mix_eval.c
@@ -0,0 +1,191 @@
+/* -*-c-*- -------------- mix_eval.c :
+ * Implementation of the functions declared in mix_eval.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/02/20 00:23:58 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "xmix_eval.h"
+
+
+static const gchar *errors_[] = {
+ N_("Successful evaluation"),
+ N_("Syntax error in expression"),
+ N_("Out of range F-specification"),
+ N_("Mismatched parenthesis"),
+ N_("Undefined symbol"),
+ N_("Internal error")
+};
+
+
+/* create a new evaluator */
+mix_eval_t *
+mix_eval_new (void)
+{
+ mix_eval_t *result = g_new (mix_eval_t, 1);
+ result->table = mix_symbol_table_new ();
+ if (result->table == NULL) {
+ g_free (result);
+ return NULL;
+ }
+ result->towner = TRUE;
+ result->value = MIX_WORD_ZERO;
+ result->errpos = 0;
+ return result;
+}
+
+/* create a new evaluator with an external symbol table */
+mix_eval_t *
+mix_eval_new_with_table (mix_symbol_table_t *table)
+{
+ mix_eval_t *result = g_new (mix_eval_t, 1);
+ result->table = table;
+ result->towner = FALSE;
+ result->value = MIX_WORD_ZERO;
+ result->errpos = 0;
+ return result;
+}
+
+/* delete */
+void
+mix_eval_delete (mix_eval_t *eval)
+{
+ g_return_if_fail (eval);
+ if (eval->table && eval->towner) {
+ mix_symbol_table_delete (eval->table);
+ }
+ g_free (eval);
+}
+
+/* eval an expression */
+mix_eval_result_t
+mix_eval_expression_with_loc (mix_eval_t *eval, const gchar *expr,
+ mix_short_t loc)
+{
+ mix_eval_data_ data;
+
+ if (expr == NULL || eval == NULL)
+ return MIX_EVAL_INTERN;
+ data.expr = g_strdup_printf ("%s\n", expr);
+ data.table = eval->table;
+ data.errpos = eval->errpos;
+ data.value = eval->value;
+ data.loc = loc;
+ eval->result = mix_eval_expr (&data);
+ if (eval->result == MIX_EVAL_OK) {
+ eval->value = data.value;
+ eval->errpos = -1;
+ } else {
+ eval->errpos = data.errpos;
+ }
+ g_free (data.expr);
+
+ return eval->result;
+}
+
+/* get the result of the last evaluation */
+mix_word_t
+mix_eval_value (const mix_eval_t *eval)
+{
+ g_return_val_if_fail (eval != NULL, MIX_WORD_ZERO);
+ return eval->value;
+}
+
+/* get the last eval result code */
+mix_eval_result_t
+mix_eval_last_error (const mix_eval_t *eval)
+{
+ g_return_val_if_fail (eval != NULL, MIX_EVAL_INTERN);
+ return eval->result;
+}
+
+/* get the last error string */
+const gchar*
+mix_eval_last_error_string (const mix_eval_t *eval)
+{
+ g_return_val_if_fail (eval != NULL, errors_[MIX_EVAL_INTERN]);
+ return errors_[eval->result];
+}
+
+/* get the position of last error */
+guint
+mix_eval_last_error_pos (const mix_eval_t *eval)
+{
+ g_return_val_if_fail (eval != NULL, 0);
+ return eval->errpos;
+}
+
+/* add, or redefine, a symbol. see mix_symbol_table.h for
+ possible outcomes. */
+gint
+mix_eval_set_symbol (mix_eval_t *eval, const gchar *symbol,
+ mix_word_t value)
+{
+ g_return_val_if_fail (eval != NULL && eval->table != NULL,
+ MIX_SYM_FAIL);
+ return mix_symbol_table_insert (eval->table, symbol, value);
+}
+
+void
+mix_eval_remove_symbol (mix_eval_t *eval, const gchar *symbol)
+{
+ g_return_if_fail (eval != NULL && eval->table != NULL);
+ mix_symbol_table_remove (eval->table, symbol);
+}
+
+void
+mix_eval_use_symbol_table (mix_eval_t *eval,
+ mix_symbol_table_t *table)
+{
+ g_return_if_fail (eval != NULL);
+ if (eval->table != NULL && eval->towner)
+ mix_symbol_table_delete (eval->table);
+ eval->table = table;
+ eval->towner = FALSE;
+}
+
+const mix_symbol_table_t *
+mix_eval_symbol_table (const mix_eval_t *eval)
+{
+ g_return_val_if_fail (eval != NULL, NULL);
+ return eval->table;
+}
+
+gboolean
+mix_eval_set_symbols_from_table (mix_eval_t *eval,
+ const mix_symbol_table_t *table)
+{
+ g_return_val_if_fail (eval != NULL, FALSE);
+ if (eval->table != NULL)
+ return mix_symbol_table_merge_table (eval->table, table);
+ else
+ return FALSE;
+}
+
+gboolean
+mix_eval_remove_symbols_from_table (mix_eval_t *eval,
+ const mix_symbol_table_t *table)
+{
+ g_return_val_if_fail (eval != NULL, FALSE);
+ if (eval->table != NULL)
+ return mix_symbol_table_substract_table (eval->table, table);
+ else
+ return FALSE;
+}
diff --git a/mixlib/mix_eval.h b/mixlib/mix_eval.h
new file mode 100644
index 0000000..a7f961f
--- /dev/null
+++ b/mixlib/mix_eval.h
@@ -0,0 +1,110 @@
+/* -*-c-*- ---------------- mix_eval.h :
+ * mix_eval_t is an evaluator of MIX W-expressions
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/02/20 00:23:58 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_EVAL_H
+#define MIX_EVAL_H
+
+#include "mix.h"
+#include "mix_types.h"
+#include "mix_symbol_table.h"
+
+/* the evaluator type */
+typedef struct mix_eval_t mix_eval_t;
+
+/* possible evaluation outcomes*/
+typedef enum {
+ MIX_EVAL_OK, /* sucess*/
+ MIX_EVAL_SYNTAX, /* syntax error */
+ MIX_EVAL_INV_FSPEC, /* out of range fspec */
+ MIX_EVAL_MIS_PAREN, /* mismatched parenthesis */
+ MIX_EVAL_UNDEF_SYM, /* undefined symbol */
+ MIX_EVAL_INTERN /* internal error */
+} mix_eval_result_t;
+
+/* create a new evaluator */
+extern mix_eval_t *
+mix_eval_new (void);
+
+/* create a new evaluator with an external symbol table */
+extern mix_eval_t *
+mix_eval_new_with_table (mix_symbol_table_t *table);
+
+/* delete */
+extern void
+mix_eval_delete (mix_eval_t *eval);
+
+/* provide a new symbol table to be used */
+extern void
+mix_eval_use_symbol_table (mix_eval_t *eval,
+ mix_symbol_table_t *table);
+
+extern const mix_symbol_table_t *
+mix_eval_symbol_table (const mix_eval_t *eval);
+
+/* eval an expression providing a value for loc counter */
+extern mix_eval_result_t
+mix_eval_expression_with_loc (mix_eval_t *eval, const gchar *expr,
+ mix_short_t loc);
+/* eval an expression with null loc*/
+#define mix_eval_expression (eval,expr) \
+ mix_eval_expression_with_loc (eval, expr, MIX_SHORT_ZERO)
+
+
+/* get the result of the last evaluation */
+extern mix_word_t
+mix_eval_value (const mix_eval_t *eval);
+
+/* get the last eval result code */
+extern mix_eval_result_t
+mix_eval_last_error (const mix_eval_t *eval);
+
+/* get the last error string */
+extern const gchar*
+mix_eval_last_error_string (const mix_eval_t *eval);
+
+/* get the position of last error */
+extern guint
+mix_eval_last_error_pos (const mix_eval_t *eval);
+
+/* add, or redefine, a symbol. see mix_symbol_table.h for
+ possible outcomes. */
+extern gint
+mix_eval_set_symbol (mix_eval_t *eval, const gchar *symbol,
+ mix_word_t value);
+
+extern gboolean
+mix_eval_set_symbols_from_table (mix_eval_t *eval,
+ const mix_symbol_table_t *table);
+
+extern void
+mix_eval_remove_symbol (mix_eval_t *eval, const gchar *symbol);
+
+extern gboolean
+mix_eval_remove_symbols_from_table (mix_eval_t *eval,
+ const mix_symbol_table_t *table);
+
+
+
+#endif /* MIX_EVAL_H */
+
diff --git a/mixlib/mix_eval_scanner.l b/mixlib/mix_eval_scanner.l
new file mode 100644
index 0000000..abf1879
--- /dev/null
+++ b/mixlib/mix_eval_scanner.l
@@ -0,0 +1,265 @@
+/* -*-c-*- ------------------ mix_eval_scanner.l :
+ * scanner used by mix_eval_t
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/02/20 00:23:58 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+%{
+#include "mix.h"
+#include "xmix_eval.h"
+
+#define YY_DECL \
+ mix_eval_result_t mix_eval_expr (mix_eval_data_ *data)
+
+ /* keep track of current position in buffer */
+#define YY_USER_ACTION yypos += yyleng;
+
+#define RETURN_STATE(err) \
+ do { \
+ done = TRUE; \
+ state = err; \
+ BEGIN (INITIAL); \
+ } while (FALSE)
+
+#define CLEAN_UP() \
+ do { \
+ yy_delete_buffer (buffer); \
+ g_free (expr_cp); \
+ } while (FALSE)
+
+static mix_word_t
+ eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y);
+
+static int
+ unput_word_ (mix_word_t word);
+
+%}
+
+%option nomain
+%option caseless
+%option pointer
+%option stack
+%option noyywrap
+%option noyy_top_state
+%option noreject
+%option outfile="lex.yy.c"
+
+%s EVAL
+%s WEVAL
+
+ws [ \t]+
+digit [0-9]
+letter [A-Z]
+number [+-]?{digit}+
+mixchar [0-9A-Z .,'')(+*/=$<>@;:\-]
+locsymbol {digit}H
+flocsymbol {digit}F
+blocsymbol {digit}B
+symbol {digit}*{letter}+[A-Z0-9]*
+binops "+"|"-"|"/"|"//"|":"
+binop {binops}|"*"
+atexpr {digit}+|{symbol}|\*
+expr [+-]?{atexpr}({binop}{1}{atexpr})*
+fpart \({expr}\)
+wexpr {expr}({fpart})?(,{expr}({fpart})?)*
+
+
+%%
+
+%{
+ YY_BUFFER_STATE buffer;
+ mix_word_t expr_val = MIX_WORD_ZERO, wexpr_val = MIX_WORD_ZERO;
+ mix_word_t wexpr_val_tmp = MIX_WORD_ZERO;
+ mix_eval_result_t state = MIX_EVAL_OK;
+ gchar *expr_cp;
+ gint yypos = -22; /* to account for padding */
+ gboolean is_fp = FALSE, done = FALSE;
+ g_assert (data != NULL && data->expr != NULL);
+ /* make room enough to unput computed values */
+ expr_cp = g_strdup_printf ("%-20s%s"," ", data->expr);
+ buffer = yy_scan_string (expr_cp);
+ data->errpos = -1;
+%}
+
+
+<*><<EOF>> {
+ CLEAN_UP ();
+ return MIX_EVAL_INTERN;
+}
+
+<INITIAL>{
+ {ws} /* eat whitespace */
+ . {
+ if (!done && state == MIX_EVAL_OK) {
+ yypos -= yyleng; yyless (0);
+ yy_push_state (WEVAL);
+ } else {
+ CLEAN_UP ();
+ if (state == MIX_EVAL_OK) return (MIX_EVAL_SYNTAX);
+ data->errpos = yypos;
+ return state;
+ }
+ }
+ "\n" {
+ CLEAN_UP();
+ if (state == MIX_EVAL_OK)
+ data->value = wexpr_val;
+ else
+ data->errpos = yypos;
+ return state;
+ }
+}
+
+<WEVAL>{
+ {number}"(" {
+ is_fp = TRUE;
+ wexpr_val_tmp = mix_word_new (atol (yytext));
+ }
+ {number}")" {
+ glong val = atol (yytext);
+ if ( !is_fp ) {
+ RETURN_STATE (MIX_EVAL_MIS_PAREN);
+ } else if ( val < 0 || val > MIX_BYTE_MAX
+ || !mix_fspec_is_valid (mix_byte_new (val)) ) {
+ RETURN_STATE (MIX_EVAL_INV_FSPEC);
+ } else {
+ is_fp = FALSE;
+ wexpr_val = mix_word_store_field (mix_byte_new (val),
+ wexpr_val_tmp,
+ wexpr_val);
+ }
+ }
+ {number}/({ws}*\n)|[,()] {
+ wexpr_val = mix_word_new (atol (yytext));
+ }
+ {expr}/({ws}*\n)|[,()] {
+ if (yytext[0] != '*')
+ {
+ yypos -= yyleng;
+ yyless (0);
+ }
+ else
+ {
+ yypos -= yyleng - 1;
+ expr_val = mix_short_to_word_fast (data->loc);
+ yyless (1);
+ }
+ yy_push_state (EVAL);
+ }
+ ,/{expr} /* eat comma if followed by expression */
+ [\t\n ] { /* ok if not inside an f-part */
+ if ( is_fp ) {
+ RETURN_STATE (MIX_EVAL_MIS_PAREN);
+ }
+ unput (yytext[yyleng-1]); --yypos;
+ done = TRUE;
+ yy_pop_state ();
+ }
+ . RETURN_STATE (MIX_EVAL_SYNTAX);
+}
+
+<EVAL>{
+ {binop}{digit}+ {
+ const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1;
+ mix_word_t value = mix_word_new (atol (s));
+ expr_val = eval_binop_ (yytext, expr_val, value);
+ }
+ {binop}{symbol} {
+ const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1;
+ if ( !mix_symbol_table_is_defined (data->table, s) ) {
+ RETURN_STATE (MIX_EVAL_UNDEF_SYM);
+ }
+ expr_val = eval_binop_ (yytext, expr_val,
+ mix_symbol_table_value (data->table, s));
+ }
+ {binop}"*" {
+ expr_val = eval_binop_ (yytext, expr_val,
+ mix_short_to_word_fast (data->loc));
+ }
+ "*" yypos -= unput_word_ (mix_short_to_word_fast (data->loc));
+ {number} expr_val = mix_word_new (atol (yytext));
+ {symbol} {
+ if ( !mix_symbol_table_is_defined (data->table, yytext) ) {
+ RETURN_STATE (MIX_EVAL_UNDEF_SYM);
+ }
+ expr_val = mix_symbol_table_value (data->table, yytext);
+ }
+ [,)(\n\t ] {
+ unput (yytext[0]); --yypos;
+ yypos -= unput_word_ (expr_val);
+ yy_pop_state ();
+ }
+
+ . RETURN_STATE (MIX_EVAL_SYNTAX);
+}
+
+
+%%
+
+static mix_word_t
+eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y)
+{
+ mix_word_t result = MIX_WORD_ZERO;
+ switch (op[0])
+ {
+ case '+':
+ result = mix_word_add (x,y);
+ break;
+ case '-':
+ result = mix_word_sub (x,y);
+ break;
+ case '*':
+ mix_word_mul (x, y, NULL, &result);
+ break;
+ case ':':
+ {
+ mix_word_t a;
+ mix_word_mul (x, 8, NULL, &a);
+ result = mix_word_add (a, y);
+ break;
+ }
+ case '/':
+ if ( strlen (op) > 1 && op[1] == '/' ) {
+ mix_word_div (x,MIX_WORD_ZERO,y, &result, NULL);
+ } else {
+ mix_word_div (MIX_WORD_ZERO, x, y, &result, NULL);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ return result;
+}
+
+
+static int
+unput_word_ (mix_word_t word)
+{
+ gchar *value;
+ gint k, result;
+ value = g_strdup_printf ("%s%ld",
+ mix_word_is_negative (word)? "-":"+",
+ mix_word_magnitude (word));
+ result = strlen (value);
+ for (k = result - 1; k >= 0; --k)
+ unput (value[k]);
+ g_free (value);
+ return result;
+}
diff --git a/mixlib/mix_file.c b/mixlib/mix_file.c
new file mode 100644
index 0000000..023f4ef
--- /dev/null
+++ b/mixlib/mix_file.c
@@ -0,0 +1,140 @@
+/* -*-c-*- -------------- mix_file.c :
+ * Implementation of the functions declared in mix_file.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "xmix_io.h"
+#include "mix_file.h"
+
+const gchar *MIX_SRC_DEFEXT = ".mixal",
+ *MIX_LIST_DEFEXT = ".mls", *MIX_CODE_DEFEXT = ".mix";
+
+/* file names completions */
+#define needs_completion_(name,defext) \
+ ( strcmp(name + strlen(name) - strlen(defext), defext) != 0 )
+
+#define add_completion_(name, defext) \
+ g_strconcat(name, defext, NULL)
+
+/* The actual definition of mix_file_t */
+struct mix_file_t
+{
+ mix_iochannel_t parent;
+ gchar *base_name;
+ gchar *ext;
+};
+
+/* Creation/destruction of files */
+static mix_file_t *
+open_file_(const gchar *name, mix_fmode_t mode)
+{
+ mix_file_t *result;
+ FILE *file;
+
+ result = g_new(mix_file_t, 1);
+ file = fopen(name, fmode_to_type_(mode));
+ if ( file == NULL ) {
+ g_free (result);
+ return NULL;
+ }
+ io_init_from_file_(MIX_IOCHANNEL(result), file);
+ return result;
+}
+
+mix_file_t *
+mix_file_new(const gchar *name, mix_fmode_t mode)
+{
+ mix_file_t *result;
+ gchar *bname;
+
+ if ( name == NULL ) return NULL;
+ bname = g_strdup(name);
+ if ( bname == NULL ) return NULL;
+ result = open_file_(name, mode);
+ if ( result == NULL )
+ {
+ g_free(bname);
+ return NULL;
+ }
+ result->base_name = bname;
+ result->ext = NULL;
+ return result;
+}
+
+/* creates a file adding to its name the defext if missing */
+mix_file_t *
+mix_file_new_with_def_ext(const gchar *name, mix_fmode_t mode,
+ const gchar *defext)
+{
+ const gchar *real_name;
+ mix_file_t *result;
+
+ if ( name == NULL ) return NULL;
+ if ( defext == NULL ) return mix_file_new(name, mode);
+ real_name = needs_completion_(name, defext) ?
+ add_completion_(name, defext) : name;
+ result = open_file_(real_name, mode);
+ if ( real_name != name ) g_free((void *)real_name);
+ if ( result == NULL ) return NULL;
+ result->ext = g_strdup(defext);
+ if ( needs_completion_(name, defext) )
+ result->base_name = g_strdup(name);
+ else
+ result->base_name = g_strndup(name, strlen(name) - strlen(defext));
+ if ( result->ext == NULL || result->base_name == NULL )
+ {
+ mix_file_delete(result);
+ return NULL;
+ }
+ return result;
+}
+
+void
+mix_file_delete(mix_file_t *file)
+{
+ g_return_if_fail(file != NULL);
+ io_close_(MIX_IOCHANNEL(file));
+ if (file->base_name) g_free(file->base_name);
+ if (file->ext) g_free(file->ext);
+ g_free(file);
+}
+
+/* convert to a standard FILE */
+extern FILE *
+mix_file_to_FILE(const mix_file_t *file)
+{
+ if ( file == NULL ) return NULL;
+ return io_get_FILE_(file);
+}
+
+/* Get the base name and extension of file */
+const gchar *
+mix_file_base_name(const mix_file_t *file)
+{
+ g_return_val_if_fail(file != NULL, NULL);
+ return file->base_name;
+}
+
+const gchar *
+mix_file_extension(const mix_file_t *file)
+{
+ g_return_val_if_fail(file != NULL, NULL);
+ return file->ext;
+}
diff --git a/mixlib/mix_file.h b/mixlib/mix_file.h
new file mode 100644
index 0000000..22bed74
--- /dev/null
+++ b/mixlib/mix_file.h
@@ -0,0 +1,61 @@
+/* -*-c-*- ---------------- mix_file.h :
+ * Declarations for the mix_file_t type.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_FILE_H
+#define MIX_FILE_H
+
+#include "mix_io.h"
+
+/* The mix_file_t type, deriving from mix_iochannel_t and
+ representing a disk file
+*/
+typedef struct mix_file_t mix_file_t;
+
+/* Creation/destruction of files */
+extern mix_file_t *
+mix_file_new(const gchar *name, mix_fmode_t mode);
+
+/* creates a file adding to its name the defext if missing */
+extern mix_file_t *
+mix_file_new_with_def_ext(const gchar *name, mix_fmode_t mode,
+ const gchar *defext);
+
+extern void
+mix_file_delete(mix_file_t *file);
+
+/* convert to a standard FILE */
+extern FILE *
+mix_file_to_FILE(const mix_file_t *file);
+
+/* standard default extensions */
+extern const gchar *MIX_SRC_DEFEXT, *MIX_LIST_DEFEXT, *MIX_CODE_DEFEXT;
+
+/* Get the base name and extension of file */
+extern const gchar *
+mix_file_base_name(const mix_file_t *file);
+
+extern const gchar *
+mix_file_extension(const mix_file_t *file);
+
+
+#endif /* MIX_FILE_H */
+
diff --git a/mixlib/mix_ins.c b/mixlib/mix_ins.c
new file mode 100644
index 0000000..2c5df08
--- /dev/null
+++ b/mixlib/mix_ins.c
@@ -0,0 +1,269 @@
+/* -*-c-*- ------------------ mix_ins.c :
+ * Implementation of the functions declared in mix_ins.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "mix_ins.h"
+
+
+struct mix_ins_desc_
+{
+ mix_opcode_t opcode;
+ mix_fspec_t def_fspec;
+ const gchar *string_rep;
+ gboolean is_ext;
+};
+
+#define IDES_(c,f,s) {c,f,#s,FALSE}
+#define IDESX_(c,f,s) {c,f,#s,TRUE}
+
+static const struct mix_ins_desc_ id_to_desc_[] = {
+ IDES_(0,0,NOP), IDES_(1,5,ADD), IDES_(2,5,SUB), IDES_(3,5,MUL),
+ IDES_(4,5,DIV),
+ IDESX_(5,0,NUM), IDESX_(5,1,CHAR), IDESX_(5,2,HLT),
+ IDESX_(6,0,SLA), IDESX_(6,1,SRA), IDESX_(6,2,SLAX), IDESX_(6,3,SRAX),
+ IDESX_(6,4,SLC), IDESX_(6,5,SRC),
+ IDES_(7,1,MOVE), IDES_(8,5,LDA), IDES_(9,5,LD1), IDES_(10,5,LD2),
+ IDES_(11,5,LD3), IDES_(12,5,LD4), IDES_(13,5,LD5),
+ IDES_(14,5,LD6), IDES_(15,5,LDX), IDES_(16,5,LDAN), IDES_(17,5,LD1N),
+ IDES_(18,5,LD2N), IDES_(19,5,LD3N), IDES_(20,5,LD4N),
+ IDES_(21,5,LD5N), IDES_(22,5,LD6N), IDES_(23,5,LDXN),
+ IDES_(24,5,STA), IDES_(25,5,ST1), IDES_(26,5,ST2), IDES_(27,5,ST3),
+ IDES_(28,5,ST4), IDES_(29,5,ST5), IDES_(30,5,ST6), IDES_(31,5,STX),
+ IDES_(32,2,STJ), IDES_(33,5,STZ), IDES_(34,0,JBUS), IDES_(35,0,IOC),
+ IDES_(36,0,IN), IDES_(37,0,OUT), IDES_(38,0,JRED),
+ IDESX_(39,0,JMP), IDESX_(39,1,JSJ), IDESX_(39,2,JOV), IDESX_(39,3,JNOV),
+ IDESX_(39,4,JL), IDESX_(39,5,JE), IDESX_(39,6,JG), IDESX_(39,7,JGE),
+ IDESX_(39,8,JNE), IDESX_(39,9,JLE),
+ IDESX_(40,0,JAN), IDESX_(40,1,JAZ), IDESX_(40,2,JAP), IDESX_(40,3,JANN),
+ IDESX_(40,4,JANZ), IDESX_(40,5,JANP),
+ IDESX_(41,0,J1N), IDESX_(41,1,J1Z), IDESX_(41,2,J1P), IDESX_(41,3,J1NN),
+ IDESX_(41,4,J1NZ), IDESX_(41,5,J1NP),
+ IDESX_(42,0,J2N), IDESX_(42,1,J2Z), IDESX_(42,2,J2P), IDESX_(42,3,J2NN),
+ IDESX_(42,4,J2NZ), IDESX_(42,5,J2NP),
+ IDESX_(43,0,J3N), IDESX_(43,1,J3Z), IDESX_(43,2,J3P), IDESX_(43,3,J3NN),
+ IDESX_(43,4,J3NZ), IDESX_(43,5,J3NP),
+ IDESX_(44,0,J4N), IDESX_(44,1,J4Z), IDESX_(44,2,J4P), IDESX_(44,3,J4NN),
+ IDESX_(44,4,J4NZ), IDESX_(44,5,J4NP),
+ IDESX_(45,0,J5N), IDESX_(45,1,J5Z), IDESX_(45,2,J5P), IDESX_(45,3,J5NN),
+ IDESX_(45,4,J5NZ), IDESX_(45,5,J5NP),
+ IDESX_(46,0,J6N), IDESX_(46,1,J6Z), IDESX_(46,2,J6P), IDESX_(46,3,J6NN),
+ IDESX_(46,4,J6NZ), IDESX_(46,5,J6NP),
+ IDESX_(47,0,JXN), IDESX_(47,1,JXZ), IDESX_(47,2,JXP), IDESX_(47,3,JXNN),
+ IDESX_(47,4,JXNZ), IDESX_(47,5,JXNP),
+ IDESX_(48,0,INCA), IDESX_(48,1,DECA), IDESX_(48,2,ENTA), IDESX_(48,3,ENNA),
+ IDESX_(49,0,INC1), IDESX_(49,1,DEC1), IDESX_(49,2,ENT1), IDESX_(49,3,ENN1),
+ IDESX_(50,0,INC2), IDESX_(50,1,DEC2), IDESX_(50,2,ENT2), IDESX_(50,3,ENN2),
+ IDESX_(51,0,INC3), IDESX_(51,1,DEC3), IDESX_(51,2,ENT3), IDESX_(51,3,ENN3),
+ IDESX_(52,0,INC4), IDESX_(52,1,DEC4), IDESX_(52,2,ENT4), IDESX_(52,3,ENN4),
+ IDESX_(53,0,INC5), IDESX_(53,1,DEC5), IDESX_(53,2,ENT5), IDESX_(53,3,ENN5),
+ IDESX_(54,0,INC6), IDESX_(54,1,DEC6), IDESX_(54,2,ENT6), IDESX_(54,3,ENN6),
+ IDESX_(55,0,INCX), IDESX_(55,1,DECX), IDESX_(55,2,ENTX), IDESX_(55,3,ENNX),
+ IDES_(56,5,CMPA), IDES_(57,5,CMP1), IDES_(58,5,CMP2), IDES_(59,5,CMP3),
+ IDES_(60,5,CMP4), IDES_(61,5,CMP5), IDES_(62,5,CMP6), IDES_(63,5,CMPX)
+};
+
+static const gsize ID_TO_DESC_SIZE_=
+ sizeof(id_to_desc_)/sizeof(id_to_desc_[0]);
+
+/* To look for the mix_ins_id corresponding to a pair (fspec,opcode)
+ we use an array indexed by opcode with values
+ (initial_ins, final_ins - initial_ins)
+*/
+struct mix_opcode_desc_
+{
+ mix_ins_id_t init_id;
+ guchar inc; /* when inc == 0, the id does not depend on fspec */
+};
+
+static struct mix_opcode_desc_ opcode_to_id_[MIX_BYTE_MAX + 1];
+
+/* a hash table mapping strings to mix_ins_id's */
+static GHashTable *string_to_id_ = NULL;
+
+void
+mix_init_ins(void)
+{
+ guint k;
+ g_assert(ID_TO_DESC_SIZE_ == mix_INVALID_INS);
+
+ for ( k = 0; k < MIX_BYTE_MAX + 1; ++k )
+ {
+ opcode_to_id_[k].init_id = mix_INVALID_INS;
+ opcode_to_id_[k].inc = 0;
+ }
+
+ for ( k = 0; k < ID_TO_DESC_SIZE_; ++k )
+ {
+ if ( opcode_to_id_[id_to_desc_[k].opcode].init_id == mix_INVALID_INS )
+ opcode_to_id_[id_to_desc_[k].opcode].init_id = k;
+ else
+ ++opcode_to_id_[id_to_desc_[k].opcode].inc;
+ }
+
+ if ( string_to_id_ == NULL )
+ {
+ string_to_id_ = g_hash_table_new(g_str_hash, g_str_equal);
+ for ( k = 0; k < ID_TO_DESC_SIZE_; ++k)
+ g_hash_table_insert(string_to_id_, (gpointer)id_to_desc_[k].string_rep,
+ GUINT_TO_POINTER(k));
+ }
+
+}
+
+void
+mix_release_ins(void)
+{
+ g_hash_table_destroy(string_to_id_);
+}
+
+/* Conversions between words and ins */
+mix_word_t
+mix_ins_to_word(const mix_ins_t *ins)
+{
+ g_return_val_if_fail(ins != NULL, MIX_WORD_ZERO);
+ return (mix_word_t)((ins->address<<18)|
+ ((ins->index&7)<<12)|(ins->fspec<<6)|(ins->opcode));
+}
+
+mix_ins_id_t
+mix_word_to_ins(mix_word_t word, mix_ins_t *ins)
+{
+ mix_ins_id_t result = mix_get_ins_id(mix_get_ins_opcode(word),
+ mix_get_ins_fspec(word));
+
+ g_return_val_if_fail(ins != NULL, result);
+ mix_word_to_ins_uncheck(word,*ins);
+ return result;
+}
+
+/* Getting ins parameters */
+mix_opcode_t
+mix_get_opcode_from_id(mix_ins_id_t id)
+{
+ g_return_val_if_fail(id < ID_TO_DESC_SIZE_, MIX_BYTE_ZERO);
+ return id_to_desc_[id].opcode;
+}
+
+gboolean
+mix_ins_id_is_extended(mix_ins_id_t id)
+{
+ g_return_val_if_fail(id < ID_TO_DESC_SIZE_, FALSE);
+ return id_to_desc_[id].is_ext;
+}
+
+
+mix_fspec_t
+mix_get_fspec_from_id(mix_ins_id_t id)
+{
+ g_return_val_if_fail(id < ID_TO_DESC_SIZE_, MIX_BYTE_ZERO);
+ return id_to_desc_[id].def_fspec;
+}
+
+
+const gchar *
+mix_get_string_from_id(mix_ins_id_t id)
+{
+ g_return_val_if_fail(id < ID_TO_DESC_SIZE_, NULL);
+ return id_to_desc_[id].string_rep;
+}
+
+mix_ins_id_t
+mix_get_id_from_string(const gchar *name)
+{
+ gpointer key, value;
+ if ( !g_hash_table_lookup_extended(string_to_id_, (gpointer)name,
+ &key, &value) )
+ return mix_INVALID_INS;
+ return (mix_ins_id_t)GPOINTER_TO_UINT(value);
+}
+
+
+mix_ins_id_t
+mix_get_ins_id(mix_opcode_t code, mix_fspec_t fspec)
+{
+ if ( opcode_to_id_[code].inc == 0 )
+ return opcode_to_id_[code].init_id;
+ else if ( opcode_to_id_[code].inc < fspec )
+ return mix_INVALID_INS;
+ else
+ return (opcode_to_id_[code].init_id + fspec);
+}
+
+/* Printable representation */
+extern gchar * /* this pointer must be freed by caller */
+mix_ins_to_string(const mix_ins_t *ins)
+{
+ gboolean needs_f;
+ gchar *result;
+ mix_ins_id_t id;
+
+ g_return_val_if_fail(ins != NULL, NULL);
+ id = mix_ins_id_from_ins(*ins);
+ needs_f = ins->fspec != id_to_desc_[id].def_fspec;
+ if ( needs_f )
+ result = g_strdup_printf("%s\t%s%d,%d(%d:%d)",
+ mix_get_string_from_id(id),
+ mix_short_is_negative(ins->address)?"-":"",
+ mix_short_magnitude(ins->address), ins->index,
+ mix_fspec_left(ins->fspec),
+ mix_fspec_right(ins->fspec));
+ else
+ result = g_strdup_printf("%s\t%s%d,%d", mix_get_string_from_id(id),
+ mix_short_is_negative(ins->address)?"-":"",
+ mix_short_magnitude(ins->address), ins->index);
+ return result;
+}
+
+extern void
+mix_ins_to_string_in_buffer (const mix_ins_t *ins, gchar *buf, guint len)
+{
+ gboolean needs_f;
+ mix_ins_id_t id;
+
+ g_return_if_fail (ins != NULL);
+ g_return_if_fail (buf != NULL);
+ id = mix_ins_id_from_ins(*ins);
+ needs_f = ins->fspec != id_to_desc_[id].def_fspec;
+ if ( needs_f )
+ g_snprintf (buf, len, "%s\t%s%d,%d(%d:%d)",
+ mix_get_string_from_id(id),
+ mix_short_is_negative(ins->address)?"-":"",
+ mix_short_magnitude(ins->address), ins->index,
+ mix_fspec_left(ins->fspec),
+ mix_fspec_right(ins->fspec));
+ else
+ g_snprintf(buf, len, "%s\t%s%d,%d",
+ mix_get_string_from_id(id),
+ mix_short_is_negative(ins->address)?"-":"",
+ mix_short_magnitude(ins->address), ins->index);
+}
+
+
+
+void
+mix_ins_print(const mix_ins_t *ins)
+{
+ g_return_if_fail(ins != NULL);
+ g_print(mix_get_string_from_id(mix_ins_id_from_ins(*ins)));
+ g_print(" %s%d,%d(%d:%d)", mix_short_is_negative(ins->address)?"-":"+",
+ mix_short_magnitude(ins->address), ins->index,
+ mix_fspec_left(ins->fspec), mix_fspec_right(ins->fspec));
+}
+
diff --git a/mixlib/mix_ins.h b/mixlib/mix_ins.h
new file mode 100644
index 0000000..7746e8c
--- /dev/null
+++ b/mixlib/mix_ins.h
@@ -0,0 +1,195 @@
+/* -*-c-*- -------------------- mix_ins.h:
+ * This file declares types and functions for manipulating MIX
+ * instructions
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_INS_H
+#define MIX_INS_H
+
+#include "mix_types.h"
+
+
+/* Initialise and free mix_ins data */
+extern void
+mix_init_ins(void);
+
+extern void
+mix_release_ins(void);
+
+/* A MIX instruction is made up of address, index, fspec and op_code */
+
+/*-- Address field: contains two bytes */
+typedef mix_short_t mix_address_t;
+
+/*-- Index field: a value between 0 and 6 */
+typedef enum {
+ mix_I0, mix_I1, mix_I2, mix_I3, mix_I4, mix_I5, mix_I6 } mix_index_t;
+
+/*-- Instruction id: enumeration of MIX instruction set */
+typedef enum {
+ mix_NOP, mix_ADD, mix_SUB, mix_MUL, mix_DIV,
+ mix_NUM, mix_CHAR, mix_HLT,
+ mix_SLA, mix_SRA, mix_SLAX, mix_SRAX, mix_SLC, mix_SRC,
+ mix_MOVE, mix_LDA, mix_LD1, mix_LD2, mix_LD3, mix_LD4, mix_LD5,
+ mix_LD6, mix_LDX, mix_LDAN, mix_LD1N, mix_LD2N, mix_LD3N, mix_LD4N,
+ mix_LD5N, mix_LD6N, mix_LDXN, mix_STA, mix_ST1, mix_ST2, mix_ST3, mix_ST4,
+ mix_ST5, mix_ST6, mix_STX, mix_STJ, mix_STZ, mix_JBUS, mix_IOC, mix_IN,
+ mix_OUT, mix_JRED,
+ mix_JMP, mix_JSJ, mix_JOV, mix_JNOV, mix_JL, mix_JE, mix_JG, mix_JGE,
+ mix_JNE, mix_JLE,
+ mix_JAN, mix_JAZ, mix_JAP, mix_JANN, mix_JANZ, mix_JANP,
+ mix_J1N, mix_J1Z, mix_J1P, mix_J1NN, mix_J1NZ, mix_J1NP,
+ mix_J2N, mix_J2Z, mix_J2P, mix_J2NN, mix_J2NZ, mix_J2NP,
+ mix_J3N, mix_J3Z, mix_J3P, mix_J3NN, mix_J3NZ, mix_J3NP,
+ mix_J4N, mix_J4Z, mix_J4P, mix_J4NN, mix_J4NZ, mix_J4NP,
+ mix_J5N, mix_J5Z, mix_J5P, mix_J5NN, mix_J5NZ, mix_J5NP,
+ mix_J6N, mix_J6Z, mix_J6P, mix_J6NN, mix_J6NZ, mix_J6NP,
+ mix_JXN, mix_JXZ, mix_JXP, mix_JXNN, mix_JXNZ, mix_JXNP,
+ mix_INCA, mix_DECA, mix_ENTA, mix_ENNA,
+ mix_INC1, mix_DEC1, mix_ENT1, mix_ENN1,
+ mix_INC2, mix_DEC2, mix_ENT2, mix_ENN2,
+ mix_INC3, mix_DEC3, mix_ENT3, mix_ENN3,
+ mix_INC4, mix_DEC4, mix_ENT4, mix_ENN4,
+ mix_INC5, mix_DEC5, mix_ENT5, mix_ENN5,
+ mix_INC6, mix_DEC6, mix_ENT6, mix_ENN6,
+ mix_INCX, mix_DECX, mix_ENTX, mix_ENNX,
+ mix_CMPA, mix_CMP1, mix_CMP2, mix_CMP3, mix_CMP4,
+ mix_CMP5, mix_CMP6, mix_CMPX, mix_INVALID_INS
+} mix_ins_id_t;
+
+/* each one of the above id's has associated an opcode, a default
+ fspec and a string representation */
+/* the opcode fits in a byte */
+typedef mix_byte_t mix_opcode_t;
+
+/* labels for each opcode */
+enum {
+ mix_opNOP = 0, mix_opADD, mix_opSUB, mix_opMUL, mix_opDIV,
+ mix_opSPC, mix_opSLx, mix_opMOVE,
+ mix_opLDA, mix_opLD1, mix_opLD2, mix_opLD3, mix_opLD4, mix_opLD5,
+ mix_opLD6, mix_opLDX, mix_opLDAN, mix_opLD1N, mix_opLD2N, mix_opLD3N,
+ mix_opLD4N, mix_opLD5N, mix_opLD6N, mix_opLDXN,
+ mix_opSTA, mix_opST1, mix_opST2, mix_opST3, mix_opST4,
+ mix_opST5, mix_opST6, mix_opSTX, mix_opSTJ, mix_opSTZ,
+ mix_opJBUS, mix_opIOC, mix_opIN, mix_opOUT, mix_opJRED,
+ mix_opJMP, mix_opJAx, mix_opJ1x, mix_opJ2x, mix_opJ3x,
+ mix_opJ4x, mix_opJ5x, mix_opJ6x, mix_opJXx,
+ mix_opINCA, mix_opINC1, mix_opINC2, mix_opINC3,
+ mix_opINC4, mix_opINC5, mix_opINC6, mix_opINCX,
+ mix_opCMPA, mix_opCMP1, mix_opCMP2, mix_opCMP3, mix_opCMP4,
+ mix_opCMP5, mix_opCMP6, mix_opCMPX
+};
+
+extern mix_opcode_t
+mix_get_opcode_from_id(mix_ins_id_t id);
+
+extern mix_fspec_t
+mix_get_fspec_from_id(mix_ins_id_t id);
+
+/* For extended instructions, both the opcode and fspec determine
+ the id (i.e., an explicit fspec cannot be used)
+*/
+extern gboolean
+mix_ins_id_is_extended(mix_ins_id_t id);
+
+extern const gchar *
+mix_get_string_from_id(mix_ins_id_t id);
+
+extern mix_ins_id_t
+mix_get_id_from_string(const gchar *name);
+
+extern mix_ins_id_t
+mix_get_ins_id(mix_opcode_t code, mix_fspec_t fspec);
+
+
+/*-- MIX instruction type */
+typedef struct mix_ins_t mix_ins_t;
+struct mix_ins_t
+{
+ mix_address_t address;
+ mix_index_t index;
+ mix_fspec_t fspec;
+ mix_opcode_t opcode;
+};
+
+#define mix_ins_fill_from_id(ins,id) \
+ do { \
+ (ins).opcode = mix_get_opcode_from_id(id); \
+ (ins).fspec = mix_get_fspec_from_id(id); \
+ } while(FALSE)
+
+
+/* A mix ins can be codified into a word */
+extern mix_word_t
+mix_ins_to_word(const mix_ins_t *ins);
+
+extern mix_ins_id_t
+mix_word_to_ins(mix_word_t w, mix_ins_t *ins);
+
+#define mix_word_add_address(word,addr) (word) |= ((addr)<<18)
+
+/* decompose an instruction codified in a word into its parts */
+#define mix_get_ins_address(word) ((mix_address_t)((word)>>18))
+#define mix_get_ins_index(word) ((mix_index_t)(((word)>>12)&7))
+#define mix_get_ins_fspec(word) ((mix_fspec_t)(mix_byte_new((word)>>6)))
+#define mix_get_ins_opcode(word) ((mix_opcode_t)(mix_byte_new(word)))
+
+/* unchecked versions for speed */
+#define mix_ins_to_word_uncheck(ins) \
+ (mix_word_t)(((ins).address<<18)| \
+ (((ins).index&7)<<12)|((ins).fspec<<6)|((ins).opcode))
+
+#define mix_word_to_ins_uncheck(word,ins) \
+ do { \
+ (ins).address = mix_get_ins_address(word); \
+ (ins).index = mix_get_ins_index(word); \
+ (ins).fspec = mix_get_ins_fspec(word); \
+ (ins).opcode = mix_get_ins_opcode(word); \
+ } while(FALSE)
+
+#define mix_ins_id_from_ins(ins) mix_get_ins_id((ins).opcode,(ins).fspec)
+
+
+/* Printable representation */
+extern gchar * /* this pointer must be freed by caller */
+mix_ins_to_string(const mix_ins_t *ins);
+
+extern void
+mix_ins_to_string_in_buffer (const mix_ins_t *ins, gchar *buf, guint len);
+
+extern void
+mix_ins_print(const mix_ins_t *ins);
+
+
+
+/* A MIX ins has an associated execution time */
+/* Initialise mix_ins data providing an interlock time for I/O devices */
+/* --------------------------------------> MOVE to VM
+typedef guint mix_time_t;
+
+extern void
+mix_init_ins_with_interlock_time(mix_time_t t);
+
+extern mix_time_t
+mix_ins_exec_time(const mix_ins_t *ins);
+*/
+
+#endif /* MIX_INS_H */
diff --git a/mixlib/mix_io.c b/mixlib/mix_io.c
new file mode 100644
index 0000000..704a5c0
--- /dev/null
+++ b/mixlib/mix_io.c
@@ -0,0 +1,219 @@
+/* -*-c-*- --------------- mix_io.c :
+ * Implementation of the functions declared in mix_io.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "xmix_io.h"
+
+mix_iochannel_t *
+mix_io_new (FILE *file)
+{
+ mix_iochannel_t *result;
+ g_return_val_if_fail (file != NULL, NULL);
+ result = g_new (mix_iochannel_t, 1);
+ result->file = file;
+ return result;
+}
+
+void
+mix_io_delete (mix_iochannel_t *ch)
+{
+ if (ch != NULL)
+ {
+ fclose (ch->file);
+ g_free (ch);
+ }
+}
+
+FILE *
+mix_io_to_FILE (mix_iochannel_t *ioc)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return ioc->file;
+}
+
+gboolean
+mix_io_eof (mix_iochannel_t *ioc)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return is_eof_ (ioc);
+}
+
+gboolean
+mix_io_is_ready (mix_iochannel_t *ioc)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return is_ready_ (ioc);
+}
+
+gboolean
+mix_io_write_byte (mix_iochannel_t *ioc, mix_byte_t b)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return write_data_ (ioc, &b, 1);
+}
+
+gboolean
+mix_io_write_byte_array (mix_iochannel_t *ioc, const mix_byte_t *b,
+ size_t s)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (b != NULL, FALSE);
+ return write_data_ (ioc, b, s);
+}
+
+
+mix_byte_t
+mix_io_read_byte (mix_iochannel_t *ioc)
+{
+ mix_byte_t result = MIX_BYTE_ZERO;
+ g_return_val_if_fail (ioc != NULL, result);
+ g_return_val_if_fail (read_data_ (ioc, &result, 1), MIX_BYTE_ZERO);
+ return result;
+}
+
+gboolean
+mix_io_read_byte_array (mix_iochannel_t *ioc, mix_byte_t *b, size_t s)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (b != NULL, FALSE);
+ return read_data_ (ioc, b, s);
+}
+
+gboolean
+mix_io_write_word (mix_iochannel_t *ioc, mix_word_t w)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return write_data_ (ioc, &w, 1);
+}
+
+gboolean
+mix_io_write_word_array (mix_iochannel_t *ioc, const mix_word_t *w,
+ size_t s)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (w != NULL, FALSE);
+ return write_data_ (ioc, &w, s);
+}
+
+mix_word_t
+mix_io_read_word (mix_iochannel_t *ioc)
+{
+ mix_word_t result = MIX_WORD_ZERO;
+ g_return_val_if_fail (ioc != NULL, result);
+ g_return_val_if_fail (read_data_ (ioc, &result, 1), MIX_WORD_ZERO);
+ return result;
+}
+
+gboolean
+mix_io_read_word_array (mix_iochannel_t *ioc, mix_word_t *w, size_t s)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (w != NULL, FALSE);
+ return read_data_ (ioc, w, s);
+}
+
+gboolean
+mix_io_write_short (mix_iochannel_t *ioc, mix_short_t w)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return write_data_ (ioc, &w, 1);
+}
+
+gboolean
+mix_io_write_short_array (mix_iochannel_t *ioc, const mix_short_t *w,
+ size_t s)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (w != NULL, FALSE);
+ return write_data_ (ioc, &w, s);
+}
+
+mix_short_t
+mix_io_read_short (mix_iochannel_t *ioc)
+{
+ mix_short_t result = MIX_SHORT_ZERO;
+ g_return_val_if_fail (ioc != NULL, result);
+ g_return_val_if_fail (read_data_ (ioc, &result, 1), MIX_SHORT_ZERO);
+ return result;
+}
+
+gboolean
+mix_io_read_short_array (mix_iochannel_t *ioc, mix_short_t *w, size_t s)
+{
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (w != NULL, FALSE);
+ return read_data_ (ioc, w, s);
+}
+
+gboolean
+mix_io_write_char (mix_iochannel_t *ioc, mix_char_t c)
+{
+ guchar value = mix_char_to_ascii (c);
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ return write_data_ (ioc, &value, 1);
+}
+
+mix_char_t
+mix_io_read_char (mix_iochannel_t *ioc)
+{
+ guchar value;
+ g_return_val_if_fail (ioc != NULL, MIX_CHAR_MAX);
+ g_return_val_if_fail (read_data_ (ioc, &value, 1), MIX_CHAR_MAX);
+ return mix_ascii_to_char (value);
+}
+
+gboolean
+mix_io_write_word_array_as_char (mix_iochannel_t *ioc,
+ const mix_word_t *w, size_t s)
+{
+ guint k, j;
+
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (w != NULL, FALSE);
+
+ for (k = 0; k < s; k++)
+ for (j = 1; j < 6; j++)
+ {
+ mix_char_t ch = mix_word_get_byte (w[k], j);
+ guchar value = mix_char_to_ascii (ch);
+ if (!write_data_ (ioc, &value, 1)) return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+mix_io_read_word_array_as_char (mix_iochannel_t *ioc,
+ mix_word_t *w, size_t s)
+{
+ guint k, j;
+
+ g_return_val_if_fail (ioc != NULL, FALSE);
+ g_return_val_if_fail (w != NULL, FALSE);
+
+ for (k = 0; k < s; k++)
+ for (j = 1; j < 6; j++)
+ {
+ guchar value;
+ if (!read_data_ (ioc, &value, 1)) return FALSE;
+ mix_word_set_byte (&w[k], j, mix_ascii_to_char (value));
+ }
+ return TRUE;
+}
diff --git a/mixlib/mix_io.h b/mixlib/mix_io.h
new file mode 100644
index 0000000..a63bda6
--- /dev/null
+++ b/mixlib/mix_io.h
@@ -0,0 +1,123 @@
+/* -*-c-*- ------------------ mix_io.h :
+ * Declarations for mix_iochannel_t and mix_file_t
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_IOCHANNEL_H
+#define MIX_IOCHANNEL_H
+
+#include <stdio.h>
+#include "mix_types.h"
+
+/* mix_iochannel_t: an object for input/output of mix types */
+typedef struct mix_iochannel_t mix_iochannel_t;
+
+/* Cast to mix_iochannel_t */
+#define MIX_IOCHANNEL(file) (mix_iochannel_t *)(file)
+
+/* I/O channels can be created in different modes: */
+typedef enum {
+ mix_io_READ, /* read existing file */
+ mix_io_WRITE, /* write new file */
+ mix_io_RDWRT, /* read/write existing from beginning */
+ mix_io_APPEND, /* append to existing or new file */
+ mix_io_RAPPEND /* read from beginning, append to end */
+} mix_fmode_t;
+
+/* Create from a file handle */
+extern mix_iochannel_t *
+mix_io_new (FILE *file);
+
+/* Delete */
+extern void
+mix_io_delete(mix_iochannel_t *ch);
+
+/* Convert to a FILE * */
+extern FILE *
+mix_io_to_FILE (mix_iochannel_t *ioc);
+
+/* Read/write from/to an iochannel */
+extern gboolean
+mix_io_eof(mix_iochannel_t *ioc);
+
+extern gboolean
+mix_io_is_ready(mix_iochannel_t *ioc);
+
+extern gboolean
+mix_io_write_byte(mix_iochannel_t *ioc, mix_byte_t b);
+
+extern gboolean
+mix_io_write_byte_array(mix_iochannel_t *ioc, const mix_byte_t *b,
+ size_t s);
+
+
+extern mix_byte_t
+mix_io_read_byte(mix_iochannel_t *ioc);
+
+extern gboolean
+mix_io_read_byte_array(mix_iochannel_t *ioc, mix_byte_t *b, size_t s);
+
+
+extern gboolean
+mix_io_write_word(mix_iochannel_t *ioc, mix_word_t w);
+
+
+extern gboolean
+mix_io_write_word_array(mix_iochannel_t *ioc, const mix_word_t *w,
+ size_t s);
+
+extern mix_word_t
+mix_io_read_word(mix_iochannel_t *ioc);
+
+extern gboolean
+mix_io_read_word_array(mix_iochannel_t *ioc, mix_word_t *w, size_t s);
+
+extern gboolean
+mix_io_write_short(mix_iochannel_t *ioc, mix_short_t w);
+
+
+extern gboolean
+mix_io_write_short_array(mix_iochannel_t *ioc, const mix_short_t *w,
+ size_t s);
+
+extern mix_short_t
+mix_io_read_short(mix_iochannel_t *ioc);
+
+extern gboolean
+mix_io_read_short_array(mix_iochannel_t *ioc, mix_short_t *w, size_t s);
+
+
+extern gboolean
+mix_io_write_char(mix_iochannel_t *ioc, mix_char_t c);
+
+extern mix_char_t
+mix_io_read_char(mix_iochannel_t *ioc);
+
+extern gboolean
+mix_io_write_word_array_as_char (mix_iochannel_t *ioc,
+ const mix_word_t *w, size_t s);
+
+extern gboolean
+mix_io_read_word_array_as_char (mix_iochannel_t *ioc,
+ mix_word_t *w, size_t s);
+
+
+#endif /* MIX_IOCHANNEL_H */
+
diff --git a/mixlib/mix_parser.c b/mixlib/mix_parser.c
new file mode 100644
index 0000000..6a58f3e
--- /dev/null
+++ b/mixlib/mix_parser.c
@@ -0,0 +1,525 @@
+/* -*-c-*- -------------- mix_parser.c :
+ * Implementation of the functions declared in mix_parser.h and
+ * xmix_parser.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "mix.h"
+#include "mix_code_file.h"
+#include "xmix_parser.h"
+
+/* The flex-generated scanner, according to file mix_parser.l */
+extern mix_parser_err_t
+mix_flex_scan (mix_parser_t *parser);
+
+/*------------ mixparser.h functions -------------------------------------*/
+
+/* error messages */
+static const gchar * const ERR_MESSAGE_[] = {
+ N_("successful compilation"),
+ N_("file not yet compiled"),
+ N_("internal error"),
+ N_("unable to open MIX source file"),
+ N_("unable to open MIX output file"),
+ N_("unexpected end of file"),
+ N_("invalid location field"),
+ N_("duplicated symbol"),
+ N_("symbol too long"),
+ N_("missing operator field"),
+ N_("unexpected location symbol"),
+ N_("invalid address field"),
+ N_("invalid index field"),
+ N_("invalid f-specification"),
+ N_("invalid operation field"),
+ N_("invalid expression"),
+ N_("undefined symbol"),
+ N_("mismatched parenthesis"),
+ N_("unexpected f-specfication"),
+ N_("missing symbol name"),
+ N_("symbol is an instruction name"),
+ N_("failed write access to code file"),
+ N_("operand of ALF pseudo instruction has less than 5 chars"),
+ N_("operand of ALF pseudo instruction has more than 5 chars")
+};
+
+static const guint NO_OF_MESSAGES_ = sizeof(ERR_MESSAGE_)/sizeof (gchar*);
+
+const gchar *
+mix_parser_err_string (mix_parser_err_t error)
+{
+ return (error < NO_OF_MESSAGES_) ? _(ERR_MESSAGE_[error]) : NULL;
+}
+
+guint
+mix_parser_err_count (const mix_parser_t *parser)
+{
+ return (parser) ? parser->err_count : 0;
+}
+
+guint
+mix_parser_warning_count (const mix_parser_t *parser)
+{
+ return (parser) ? parser->warn_count : 0;
+}
+
+const gchar *
+mix_parser_src_file_base_name (const mix_parser_t *parser)
+{
+ return (parser) ? mix_file_base_name (parser->in_file) : NULL;
+}
+
+const gchar *
+mix_parser_src_file_extension (const mix_parser_t *parser)
+{
+ return (parser) ? mix_file_extension (parser->in_file) : NULL;
+}
+
+
+/* Create/destroy a mix_parser */
+/* compare function for the table of ins */
+static gint
+compare_shorts_ (gconstpointer s1, gconstpointer s2)
+{
+ mix_short_t a = (mix_short_t)GPOINTER_TO_UINT(s1);
+ mix_short_t b = (mix_short_t)GPOINTER_TO_UINT (s2);
+ if ( mix_short_sign (a) == mix_short_sign (b) )
+ return mix_short_magnitude (a) - mix_short_magnitude (b);
+ else if ( mix_short_magnitude (a) == 0 && mix_short_magnitude (b) == 0 )
+ return 0;
+ else if ( mix_short_is_positive (a) )
+ return 1;
+ return -1;
+}
+
+mix_parser_t *
+mix_parser_new (const gchar *in_file)
+{
+ mix_parser_t *result;
+ mix_file_t *f = mix_file_new_with_def_ext (in_file, mix_io_READ,
+ MIX_SRC_DEFEXT);
+
+ if ( f == NULL ) return NULL;
+ result = g_new (mix_parser_t, 1);
+ result->symbol_table = mix_symbol_table_new ();
+ result->ls_table = mix_symbol_table_new ();
+ result->cur_ls = 0;
+ result->future_refs = g_hash_table_new (g_str_hash, g_str_equal);
+ result->ins_table = g_tree_new (compare_shorts_);
+ if ( result->symbol_table == NULL || result->future_refs == NULL
+ || result->ins_table == NULL || result->ls_table == NULL )
+ {
+ mix_symbol_table_delete (result->symbol_table);
+ mix_symbol_table_delete (result->ls_table);
+ g_hash_table_destroy (result->future_refs);
+ g_tree_destroy (result->ins_table);
+ mix_file_delete (f);
+ g_free (result);
+ g_warning (_("No system resources"));
+ return NULL;
+ }
+ result->in_file = f;
+ result->loc_count = MIX_SHORT_ZERO;
+ result->status = MIX_PERR_NOCOMP;
+ result->err_line = 0;
+ result->err_count = 0;
+ result->warn_count = 0;
+ return result;
+}
+
+static void
+delete_list_vals_ (gpointer key, gpointer value, gpointer data)
+{
+ g_free (key);
+ g_slist_free ((GSList*)value);
+}
+
+static int
+delete_tree_vals_ (gpointer key, gpointer value, gpointer data)
+{
+ g_free (value);
+ return FALSE;
+}
+
+void
+mix_parser_delete (mix_parser_t *parser)
+{
+ g_return_if_fail (parser != NULL);
+ /* clear the GSList values of future_refs and its keys */
+ g_hash_table_foreach (parser->future_refs, delete_list_vals_, NULL);
+ /* clear the ins_node_'s of the ins tree */
+ g_tree_traverse (parser->ins_table, delete_tree_vals_, G_IN_ORDER, NULL);
+ /* destroy the tree and hash tables */
+ g_tree_destroy (parser->ins_table);
+ mix_symbol_table_delete (parser->symbol_table);
+ mix_symbol_table_delete (parser->ls_table);
+ g_hash_table_destroy (parser->future_refs);
+ mix_file_delete (parser->in_file);
+ g_free (parser);
+}
+
+/* Compile a mix source file */
+static gboolean
+undef_warning_ (gpointer symbol, gpointer value, gpointer data)
+{
+ mix_parser_log_error ((mix_parser_t *)data, MIX_PERR_UNDEF_SYM, 1,
+ (const gchar *)symbol, TRUE);
+ /* move the symbol to the symbol table */
+ mix_symbol_table_insert_static (((mix_parser_t *)data)->symbol_table,
+ symbol, MIX_WORD_ZERO);
+ return TRUE;
+}
+
+static void
+update_future_refs_value_ (mix_parser_t *parser, const gchar *name,
+ mix_short_t value)
+{
+ GSList *list = NULL;
+ gpointer key;
+
+ g_assert (parser != NULL && name != NULL);
+ if ( g_hash_table_lookup_extended (parser->future_refs, name, &key,
+ (gpointer *)&list) )
+ {
+ GSList *tmp = list;
+ ins_node_ *node;
+ while ( tmp != NULL )
+ {
+ node =
+ (ins_node_ *)g_tree_lookup (parser->ins_table,tmp->data);
+ g_assert (node);
+ if (mix_get_ins_address (node->ins) == 1) {
+ value = mix_short_negative (value);
+ node->ins = mix_word_set_field (node->ins,
+ MIX_WORD_ZERO,
+ mix_fspec_new (1,2));
+ }
+ mix_word_add_address (node->ins, value);
+ g_tree_insert (parser->ins_table, tmp->data, (gpointer)node);
+ tmp = g_slist_next (tmp);
+ }
+ g_hash_table_remove (parser->future_refs, name);
+ g_free (key);
+ g_slist_free (list);
+ }
+}
+
+#define update_future_refs_(parser,name) \
+ update_future_refs_value_(parser, name, (parser)->loc_count);
+
+static void
+update_ls_ (gpointer symbol, gpointer value, gpointer parser)
+{ /* add an instruction on current location and update refs to it */
+ mix_ins_t ins;
+ mix_word_t w = (mix_word_t) GPOINTER_TO_UINT (value);
+ mix_parser_t *par = (mix_parser_t *) parser;
+
+ mix_word_to_ins_uncheck (w, ins);
+ mix_parser_add_ins (par, &ins, 0);
+ update_future_refs_ (par, (const gchar *)symbol);
+ par->loc_count++;
+}
+
+mix_parser_err_t
+mix_parser_compile (mix_parser_t *parser)
+{
+ g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL);
+ g_return_val_if_fail (parser->in_file != NULL, MIX_PERR_NOIN);
+ g_return_val_if_fail (parser->symbol_table != NULL, MIX_PERR_INTERNAL);
+ g_return_val_if_fail (parser->future_refs != NULL, MIX_PERR_INTERNAL);
+ g_return_val_if_fail (parser->ins_table != NULL, MIX_PERR_INTERNAL);
+
+ parser->status = mix_flex_scan (parser);
+ if ( parser->status == MIX_PERR_OK )
+ {
+ mix_symbol_table_foreach (parser->ls_table, update_ls_,
+ (gpointer)parser);
+ g_hash_table_foreach_remove (parser->future_refs,
+ undef_warning_, (gpointer)parser);
+ }
+
+ return parser->status;
+}
+
+/* Write a compiled source to a code file */
+struct write_code_context_
+{
+ mix_code_file_t *file;
+ mix_parser_t *parser;
+};
+
+static gint
+write_code_ (gpointer address, gpointer ins_node, gpointer context)
+{
+ mix_ins_desc_t desc;
+ struct write_code_context_ *cntx = (struct write_code_context_ *)context;
+ desc.ins = ((ins_node_ *)ins_node)->ins;
+ desc.lineno = ((ins_node_ *)ins_node)->lineno;
+ desc.address = (mix_address_t)GPOINTER_TO_UINT (address);
+ if ( mix_code_file_write_ins (cntx->file, &desc) )
+ return FALSE;
+ else
+ {
+ cntx->parser->status = MIX_PERR_NOWRITE;
+ return TRUE;
+ }
+}
+
+mix_parser_err_t
+mix_parser_write_code (mix_parser_t *parser, const gchar *code_file,
+ gboolean debug)
+{
+ struct write_code_context_ context;
+ const gchar *cfname = (code_file) ?
+ code_file : mix_file_base_name (parser->in_file);
+ gchar *dir;
+ gchar *source_path;
+
+ g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL);
+ if (parser->status != MIX_PERR_OK ) return parser->status;
+ context.parser = parser;
+ dir = g_get_current_dir ();
+ source_path = g_strconcat (dir, G_DIR_SEPARATOR_S,
+ mix_file_base_name (parser->in_file), NULL);
+ context.file = mix_code_file_new_write (cfname, parser->start, source_path,
+ debug, parser->symbol_table);
+ g_free (dir);
+ g_free (source_path);
+ if (context.file == NULL) return MIX_PERR_NOOUT;
+ g_tree_traverse (parser->ins_table, write_code_,
+ G_IN_ORDER, (gpointer)&context);
+ mix_code_file_delete (context.file);
+ return parser->status;
+}
+
+/* Produce a listing file summarising the compilation */
+static gint
+write_listing_ (gpointer address, gpointer ins, gpointer context)
+{
+ guint k;
+ FILE *file = (FILE *)context;
+ ins_node_ *ins_node = (ins_node_ *)ins;
+ mix_ins_t instruct;
+ gchar *instext = NULL;
+
+ mix_ins_id_t id = mix_word_to_ins (ins_node->ins, &instruct);
+ if (id != mix_INVALID_INS)
+ instext = mix_ins_to_string (&instruct);
+ fprintf (file, "%d\t%s ", GPOINTER_TO_INT (address),
+ mix_word_is_negative (ins_node->ins)? "-":"+");
+ for ( k = 1; k < 6; ++k )
+ fprintf (file, "%02d ", mix_word_get_byte (ins_node->ins, k));
+ fprintf (file, _("\t%s\t(line %d)\n"), instext? instext:"--DATA--",
+ ins_node->lineno);
+ if (instext) g_free (instext);
+ return FALSE;
+}
+
+mix_parser_err_t
+mix_parser_write_listing (mix_parser_t *parser, const gchar *list_file)
+{
+ FILE *file;
+ mix_file_t *mfile;
+ const gchar *name;
+
+ g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL);
+ if (parser->status != MIX_PERR_OK ) return parser->status;
+ name = (list_file) ? list_file : mix_file_base_name (parser->in_file);
+ mfile = mix_file_new_with_def_ext (name, mix_io_WRITE, MIX_LIST_DEFEXT);
+ if ( mfile == NULL ) return MIX_PERR_NOOUT;
+ file = mix_file_to_FILE (mfile);
+ fprintf (file, _("*** %s%s: compilation summary ***\n\n"),
+ mix_file_base_name (parser->in_file),
+ mix_file_extension (parser->in_file));
+ fputs ( _("*** Address / Compiled word / Symbolic rep / Source file line\n"),
+ file);
+ g_tree_traverse (parser->ins_table, write_listing_,
+ G_IN_ORDER, (gpointer)file);
+ fprintf (file, _("\n*** Start address: %d\n"),
+ mix_short_magnitude (parser->start));
+ fprintf (file, _("\n*** Symbol table\n"));
+ mix_symbol_table_print (parser->symbol_table, MIX_SYM_ROWS, file, TRUE);
+ fprintf (file, _("\n*** End of summary ***\n"));
+ mix_file_delete (mfile);
+ return parser->status;
+}
+
+/* load a virtual machine's memory with the contents of a compiled file */
+static gint
+load_vm_ (gpointer address, gpointer ins, gpointer vm)
+{
+ mix_vm_set_addr_contents ((mix_vm_t*)vm,
+ (mix_address_t)GPOINTER_TO_UINT (address),
+ ((ins_node_ *)ins)->ins);
+ return FALSE;
+}
+
+mix_parser_err_t
+mix_parser_load_vm (const mix_parser_t *parser, mix_vm_t *vm)
+{
+ g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL);
+ g_return_val_if_fail (vm != NULL, MIX_PERR_INTERNAL);
+ g_return_val_if_fail (parser->status == MIX_PERR_OK, parser->status);
+ mix_vm_reset (vm);
+ g_tree_traverse (parser->ins_table, load_vm_, G_IN_ORDER, (gpointer)vm);
+ mix_vm_set_start_addr (vm, parser->start);
+ return parser->status;
+}
+
+
+
+/*------------ xmiparser.h functions -------------------------------------*/
+/* functions to manipulate mix_parser_t during compilation */
+
+
+/* symbol table */
+/* Define a new symbol with value equal to the current loc_count
+ * and update future refs to this symbol
+ */
+mix_parser_err_t
+mix_parser_define_symbol_here (mix_parser_t *parser, const gchar *name)
+{
+ mix_word_t value = mix_short_to_word_fast (parser->loc_count);
+ return mix_parser_define_symbol_value (parser, name, value);
+}
+
+mix_parser_err_t
+mix_parser_define_symbol_value (mix_parser_t *parser, const gchar *name,
+ mix_word_t value)
+{
+ g_assert (parser != NULL && name != NULL);
+
+ switch (mix_symbol_table_add (parser->symbol_table, name, value))
+ {
+ case MIX_SYM_OK:
+ if ( parser->status == MIX_PERR_NOCOMP )
+ update_future_refs_value_ (parser, name, value);
+ return MIX_PERR_OK;
+ case MIX_SYM_LONG: return MIX_PERR_LONG_SYMBOL;
+ case MIX_SYM_DUP: return MIX_PERR_DUP_SYMBOL;
+ default: return MIX_PERR_INTERNAL;
+ }
+}
+
+/* Obtain the value of a symbol */
+void
+mix_parser_set_future_ref (mix_parser_t *parser, const gchar *name)
+{
+ const gchar *nname = name;
+ GSList *list;
+
+ g_assert (parser != NULL && name != NULL);
+
+ if ( parser->status == MIX_PERR_NOCOMP )
+ {
+ list = g_hash_table_lookup (parser->future_refs, name);
+ if ( list == NULL ) nname = g_strdup (name);
+ list = g_slist_prepend (list, (gpointer)((guint)parser->loc_count));
+ g_hash_table_insert (parser->future_refs, (gpointer)nname, list);
+ }
+}
+
+/* Redefine the value of a local symbol as the current loc_count */
+void
+mix_parser_manage_local_symbol (mix_parser_t *parser, const gchar *name,
+ mix_short_t value)
+{
+ gchar ref[3];
+ ref[2] = 0;
+
+ g_assert (parser != NULL && name != NULL);
+ g_assert (strlen(name) == 2);
+
+ switch (name[1])
+ {
+ case 'f': case 'F':
+ mix_parser_set_future_ref (parser, name);
+ break;
+ case 'h': case 'H':
+ ref[0] = name[0];
+ ref[1] = 'F';
+ if ( parser->status == MIX_PERR_NOCOMP )
+ update_future_refs_value_ (parser, ref, value);
+ ref[1] = 'B';
+ mix_symbol_table_insert (parser->symbol_table, ref,
+ mix_short_to_word_fast (value));
+ break;
+ default:
+ return;
+ }
+}
+
+/* Literal strings symbols */
+void
+mix_parser_define_ls (mix_parser_t *parser, mix_word_t value)
+{
+ gchar *name = g_strdup_printf ("%05d", parser->cur_ls++);
+ mix_symbol_table_add (parser->ls_table, name, value);
+ mix_parser_set_future_ref (parser, name);
+ g_free (name);
+}
+
+/* Compilation */
+void
+mix_parser_add_ins (mix_parser_t *parser, const mix_ins_t *new_ins,
+ guint lineno)
+{
+ g_assert (parser != NULL && new_ins != NULL);
+ mix_parser_add_raw (parser, mix_ins_to_word_uncheck (*new_ins), lineno);
+}
+
+void
+mix_parser_add_raw (mix_parser_t *parser, mix_word_t word, guint lineno)
+{
+ g_assert (parser != NULL);
+ if ( parser->status == MIX_PERR_NOCOMP || parser->status == MIX_PERR_OK )
+ {
+ ins_node_ *node = g_new (ins_node_, 1);
+ node->ins = word;
+ node->lineno = lineno;
+ g_tree_insert (parser->ins_table, (gpointer)((guint)parser->loc_count),
+ (gpointer)node);
+ }
+}
+
+/* Error handling */
+void
+mix_parser_log_error (mix_parser_t *parser, mix_parser_err_t error,
+ gint lineno, const gchar *comment, gboolean warn)
+{
+ g_assert (parser != NULL);
+ if ( warn )
+ parser->warn_count += 1;
+ else
+ {
+ parser->err_count += 1;
+ parser->err_line = lineno;
+ parser->status = error;
+ }
+
+ fprintf (stderr, "%s%s:%d: %s: %s",
+ mix_file_base_name (parser->in_file),
+ mix_file_extension (parser->in_file),
+ lineno, warn ? _("warning"):_("error"), _(ERR_MESSAGE_[error]));
+
+ if (comment != NULL)
+ fprintf (stderr, ": %s\n", comment);
+ else
+ fputs ("\n", stderr);
+}
+
diff --git a/mixlib/mix_parser.h b/mixlib/mix_parser.h
new file mode 100644
index 0000000..f371430
--- /dev/null
+++ b/mixlib/mix_parser.h
@@ -0,0 +1,110 @@
+/* -*-c-*- ---------------- mix_parser.h :
+ * Declarations for mix_parser_t, which compiles a source file into
+ * a mix code file.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_PARSER_H
+#define MIX_PARSER_H
+
+#include <glib.h>
+#include "mix_vm.h"
+
+/* The parser type */
+typedef struct mix_parser_t mix_parser_t;
+
+/* Create/destroy a mix_parser */
+extern mix_parser_t *
+mix_parser_new(const gchar *in_file);
+
+extern void
+mix_parser_delete(mix_parser_t *parser);
+
+/* Access source file name */
+extern const gchar *
+mix_parser_src_file_base_name(const mix_parser_t *parser);
+
+extern const gchar *
+mix_parser_src_file_extension(const mix_parser_t *parser);
+
+/* Compile a mix source file */
+/* compilation errors */
+typedef enum {
+ MIX_PERR_OK, /* no error */
+ MIX_PERR_NOCOMP, /* file not yet compiled */
+ MIX_PERR_INTERNAL, /* internal error */
+ MIX_PERR_NOIN, /* unable to open input file */
+ MIX_PERR_NOOUT, /* unable to open output file */
+ MIX_PERR_UNEX_EOF, /* unexpected end of file */
+ MIX_PERR_INV_LOC, /* invalid loc field */
+ MIX_PERR_DUP_SYMBOL, /* duplicated symbol */
+ MIX_PERR_LONG_SYMBOL, /* symbol name too long */
+ MIX_PERR_NOOP, /* missing op field */
+ MIX_PERR_UNEX_LOC, /* unexpected location symbol */
+ MIX_PERR_INV_ADDRESS, /* invalid address field */
+ MIX_PERR_INV_IDX, /* invalid index field */
+ MIX_PERR_INV_FSPEC, /* invalid fspec */
+ MIX_PERR_INV_OP, /* invalid operation */
+ MIX_PERR_INV_EXPR, /* invalid expression */
+ MIX_PERR_UNDEF_SYM, /* undefined symbol */
+ MIX_PERR_MIS_PAREN, /* mismatched parenthesis */
+ MIX_PERR_UNEX_FSPEC, /* unexpected f-spec */
+ MIX_PERR_MIS_SYM, /* missing symbol name */
+ MIX_PERR_SYM_INS, /* symbol has the same name as instruction */
+ MIX_PERR_NOWRITE, /* failed code write */
+ MIX_PERR_SHORT_ALF, /* short ALF operand */
+ MIX_PERR_LONG_ALF /* too long ALF operand */
+} mix_parser_err_t;
+
+extern const gchar *
+mix_parser_err_string(mix_parser_err_t error);
+
+extern mix_parser_err_t
+mix_parser_compile(mix_parser_t *parser);
+
+extern guint
+mix_parser_warning_count(const mix_parser_t *parser);
+
+extern guint
+mix_parser_err_count(const mix_parser_t *parser);
+
+/* Write the compilation result to a code file with the given name.
+ code_file is completed, if required, with the requisite extension;
+ if code_file == NULL [source_file_name].[extension] is used.
+ If debug == TRUE, debug information is written.
+*/
+extern mix_parser_err_t
+mix_parser_write_code(mix_parser_t *parser, const gchar *code_file,
+ gboolean debug);
+
+/* Write a "canonical" listing of a compiled source, i.e. a source
+ file with all symbols substituted by their actual values after
+ compilation.
+*/
+extern mix_parser_err_t
+mix_parser_write_listing(mix_parser_t *parser, const gchar *list_file);
+
+/* load a virtual machine's memory with the contents of a compiled file */
+extern mix_parser_err_t
+mix_parser_load_vm(const mix_parser_t *parser, mix_vm_t *vm);
+
+
+#endif /* MIX_PARSER_H */
+
diff --git a/mixlib/mix_scanner.l b/mixlib/mix_scanner.l
new file mode 100644
index 0000000..f961fe6
--- /dev/null
+++ b/mixlib/mix_scanner.l
@@ -0,0 +1,532 @@
+/* ------------------ mix_scanner.l :
+ * Lexical scanner used by mix_parser_t
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+%{
+#include "mix.h"
+#include "xmix_parser.h"
+
+#define YY_DECL mix_parser_err_t mix_flex_scan (mix_parser_t *parser)
+
+#define RESET() \
+ do { \
+ mix_ins_fill_from_id (ins, mix_NOP); \
+ ins.address = 0; \
+ ins.index = 0; \
+ nof = FALSE; \
+ lsf = FALSE; \
+ if (symbol != NULL ) \
+ { \
+ g_free (symbol); \
+ symbol = NULL; \
+ } \
+ if (lsymbol != NULL) \
+ { \
+ g_free (lsymbol); \
+ lsymbol = NULL; \
+ } \
+ } while (FALSE)
+
+#define NEXT() \
+ do { \
+ if (lsymbol != NULL) \
+ mix_parser_manage_local_symbol (parser,lsymbol, \
+ loc); \
+ parser->loc_count++; \
+ RESET (); \
+ ++lineno; \
+ BEGIN (INITIAL); \
+ } while (FALSE)
+
+#define ADD_INS() \
+ do { \
+ mix_parser_add_ins (parser, &ins, lineno); \
+ NEXT (); \
+ } while (FALSE)
+
+#define ADD_RAW(value) \
+ do { \
+ mix_parser_add_raw (parser, value, lineno); \
+ NEXT (); \
+ } while (FALSE)
+
+
+#define ENTER_EVAL() \
+ do { \
+ if (yytext[0] != '*') \
+ { \
+ expr_val = MIX_WORD_ZERO; \
+ yyless (0); \
+ } \
+ else \
+ { \
+ expr_val = mix_short_to_word_fast (parser->loc_count); \
+ yyless (1); \
+ } \
+ yy_push_state (EVAL); \
+ } while (FALSE)
+
+#define ENTER_WEVAL() \
+ do { \
+ wexpr_val = MIX_WORD_ZERO; \
+ wexpr_val_tmp = MIX_WORD_ZERO; \
+ is_fp = FALSE; \
+ yyless (0); \
+ yy_push_state (WEVAL); \
+ } while (FALSE)
+
+#define RETURN_ERROR(error, comment) \
+ do { \
+ char c; \
+ mix_parser_log_error (parser,error,lineno,comment,FALSE); \
+ while ( (c = input ()) != '\n' && c != EOF ) ; \
+ if ( c == EOF ) return error; else ++lineno; \
+ RESET (); \
+ BEGIN (INITIAL); \
+ } while (FALSE)
+
+
+static mix_word_t
+ eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y);
+
+static void
+ unput_word_ (mix_word_t word);
+
+%}
+
+%option nomain
+%option caseless
+%option pointer
+%option stack
+%option noyywrap
+%option noyy_top_state
+%option noreject
+%option outfile="lex.yy.c"
+
+%s LOC
+%s OP
+%s ADDRESS
+%s INDEX
+%s FSPEC
+%s EVAL
+%s WEVAL
+%s ORIG
+%s CON
+%s EQU
+%s END
+
+ws [ \t]+
+digit [0-9]
+letter [A-Z]
+number [+-]?{digit}+
+mixchar [0-9A-Z .,'')(+*/=$<>@;:\-]
+locsymbol {digit}H
+flocsymbol {digit}F
+blocsymbol {digit}B
+symbol {digit}*{letter}+[A-Z0-9]*
+binop "+"|"-"|"*"|"/"|"//"|":"
+atexpr {digit}+|{symbol}|\*
+expr [+-]?{atexpr}({binop}{1}{atexpr})*
+fpart \({expr}\)
+wexpr {expr}({fpart})?(,{expr}({fpart})?)*
+
+
+%%
+
+%{
+
+ mix_ins_t ins;
+ gboolean nof = FALSE, is_fp = FALSE, end = FALSE, lsf = FALSE;
+ mix_word_t expr_val = MIX_WORD_ZERO, wexpr_val = MIX_WORD_ZERO,
+ wexpr_val_tmp = MIX_WORD_ZERO;
+ gchar *symbol = NULL, *lsymbol = NULL;
+ mix_address_t loc = MIX_SHORT_ZERO;
+ guint lineno = 1;
+ mix_ins_fill_from_id (ins, mix_NOP);
+ ins.address = 0;
+ ins.index = 0;
+ parser->err_line = 0;
+ yyin = mix_file_to_FILE (parser->in_file);
+
+%}
+
+
+<*><<EOF>> {
+ mix_parser_log_error (parser, MIX_PERR_UNEX_EOF, lineno, NULL, FALSE);
+ return MIX_PERR_UNEX_EOF;
+}
+
+<INITIAL>{
+ ^\*.* /* eat comments */
+ . {
+ if ( end ) return parser->status;
+ yyless (0);
+ BEGIN (LOC);
+ }
+ \n {
+ ++lineno;
+ if ( end ) return parser->status;
+ }
+}
+
+<LOC>{
+ {ws}+ BEGIN (OP); /* LOC field is empty */
+ {locsymbol} { /* manage local symbol */
+ loc = get_ploc_ (parser);
+ lsymbol = g_strdup (yytext);
+ if ( lsymbol == NULL ) {
+ mix_parser_log_error (parser, MIX_PERR_INTERNAL, lineno, NULL, FALSE);
+ return MIX_PERR_INTERNAL;
+ }
+ BEGIN (OP);
+ }
+ {locsymbol}/({ws}+EQU) {/* local symbol with value */
+ loc = get_ploc_ (parser);
+ symbol = g_strdup (yytext);
+ lsymbol = g_strdup (yytext);
+ if ( symbol == NULL || lsymbol == NULL) {
+ mix_parser_log_error (parser, MIX_PERR_INTERNAL, lineno, NULL, FALSE);
+ return MIX_PERR_INTERNAL;
+ }
+ symbol[1] = 'B'; /* this will be referred as nB afterwards */
+ BEGIN (OP);
+ }
+ {flocsymbol}|{blocsymbol} RETURN_ERROR (MIX_PERR_UNEX_LOC, yytext);
+ {symbol}/({ws}+EQU) { /* store symbol name for future definition */
+ symbol = g_strdup (yytext);
+ if ( symbol == NULL ) {
+ mix_parser_log_error (parser, MIX_PERR_INTERNAL, lineno, NULL, FALSE);
+ return MIX_PERR_INTERNAL;
+ }
+ BEGIN (OP);
+ }
+ {symbol} { /* define a new symbol */
+ mix_parser_err_t err;
+ if ( mix_get_id_from_string (yytext) != mix_INVALID_INS )
+ mix_parser_log_error (parser, MIX_PERR_SYM_INS, lineno, yytext, TRUE);
+ if ( (err = mix_parser_define_symbol_here (parser,yytext)) != MIX_PERR_OK )
+ mix_parser_log_error (parser, err, lineno, yytext, FALSE);
+ BEGIN (OP);
+ }
+ . RETURN_ERROR (MIX_PERR_INV_LOC, yytext);
+ \n ++lineno; /* empty line */
+}
+
+<OP>{
+ {ws} /* eat leading whitespace */
+ \n RETURN_ERROR (MIX_PERR_NOOP, NULL);
+ ORIG{ws}+ BEGIN (ORIG);
+ CON{ws}+ BEGIN (CON);
+ EQU{ws}+ BEGIN (EQU);
+ END{ws}+ BEGIN (END);
+ ALF{ws}+\"{mixchar}{5,}\"{ws}+.*\n |
+ ALF{ws}+\"{mixchar}{5,}\"{ws}*\n {
+ mix_byte_t bytes[5];
+ mix_word_t value;
+ guint k, j = 4;
+
+ while ( yytext[j++] != '\"' ) ;
+ for ( k = j; k < 5+j && yytext[k] != '\"'; ++k )
+ bytes[k-j] = mix_ascii_to_char (yytext[k]);
+ if ( k-j < 5 )
+ mix_parser_log_error (parser, MIX_PERR_SHORT_ALF, lineno, NULL, TRUE);
+ else if ( yytext[k] != '\"' )
+ mix_parser_log_error (parser, MIX_PERR_LONG_ALF, lineno, NULL, TRUE);
+
+ value = mix_bytes_to_word (bytes, 5);
+
+ ADD_RAW (value);
+ }
+ [A-Z0-9]+{ws}*/\n |
+ [A-Z0-9]+{ws}+ {
+ mix_ins_id_t id = mix_get_id_from_string (g_strchomp (yytext));
+ if ( id == mix_INVALID_INS )
+ mix_parser_log_error (parser, MIX_PERR_INV_OP, lineno, yytext, FALSE);
+ else {
+ mix_ins_fill_from_id (ins, id);
+ nof = mix_ins_id_is_extended (id);
+ }
+ BEGIN (ADDRESS);
+ }
+ {expr} RETURN_ERROR (MIX_PERR_INV_OP, yytext);
+ . RETURN_ERROR (MIX_PERR_INV_OP, yytext);
+}
+
+
+<ORIG>{
+ {number}{ws}*\n |
+ {number}{ws}+.*\n {
+ mix_word_t value = mix_word_new (atol (yytext));
+ parser->loc_count = mix_word_to_short_fast (value);
+ ++lineno;
+ BEGIN (INITIAL);
+ }
+}
+
+<CON>{
+ {number}{ws}*\n |
+ {number}{ws}+.*\n {
+ mix_word_t value = mix_word_new (atol (yytext));
+ mix_word_to_ins_uncheck (value, ins);
+ ADD_INS ();
+ }
+}
+
+<EQU>{
+ {number}{ws}*\n |
+ {number}{ws}+.*\n {
+ mix_word_t value;
+ gint def;
+ if ( symbol == NULL ) RETURN_ERROR (MIX_PERR_MIS_SYM, NULL);
+ value = mix_word_new (atol (yytext));
+ def = mix_parser_define_symbol_value (parser, symbol, value);
+ if ( def == MIX_SYM_DUP ) RETURN_ERROR (MIX_PERR_DUP_SYMBOL, symbol);
+ if ( def == MIX_SYM_LONG ) RETURN_ERROR (MIX_PERR_LONG_SYMBOL, symbol);
+ ++lineno;
+ BEGIN (INITIAL);
+ }
+}
+
+<END>{
+ {number}{ws}*\n |
+ {number}{ws}+.*\n {
+ parser->start = mix_short_new (atol (yytext));
+ end = TRUE;
+ if ( parser->status == MIX_PERR_NOCOMP ) parser->status = MIX_PERR_OK;
+ return parser->status;
+ }
+}
+
+<ORIG,CON,EQU,END>{
+ {wexpr} ENTER_WEVAL ();
+ . RETURN_ERROR (MIX_PERR_INV_OP, yytext);
+}
+
+
+<ADDRESS,INDEX,FSPEC>{locsymbol} RETURN_ERROR (MIX_PERR_UNEX_LOC, yytext);
+
+<ADDRESS>{
+ =/[+-]?{number}= lsf = TRUE;
+ =/{expr}= lsf = TRUE;
+ [+-]?{number}={ws}*\n |
+ [+-]?{number}={ws}+.*\n {
+ if (!lsf) RETURN_ERROR (MIX_PERR_INV_ADDRESS, yytext);
+ mix_parser_define_ls (parser, mix_word_new (atol (yytext)));
+ ADD_INS ();
+ }
+ [+-]?{number}{ws}+.*\n |
+ [+-]?{number}[(,\n] {
+ ins.address = mix_short_new (atol (yytext));
+ switch ( yytext[yyleng-1] ) {
+ case '(' : BEGIN (FSPEC); break;
+ case ',' : BEGIN (INDEX); break;
+ case '\n' : ADD_INS (); break;
+ default: g_assert_not_reached ();
+ }
+ }
+ ([+-]?{symbol})/[(,\n\t ] {
+ gboolean neg = (yytext[0] == '-');
+ const gchar *s = (neg || yytext[0] == '+')? yytext+1 : yytext;
+ if ( !mix_symbol_table_is_defined (parser->symbol_table, s) )
+ {
+ mix_parser_set_future_ref (parser, s);
+ if (neg)
+ mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, lineno, s, TRUE);
+ unput (neg? '1':'0');
+ }
+ else
+ {
+ mix_word_t v = mix_symbol_table_value (parser->symbol_table, s);
+ if ( neg ) mix_word_reverse_sign (v);
+ unput_word_ (v);
+ }
+ }
+ {expr}/[(,=\n\t ] ENTER_EVAL ();
+ \n ADD_INS ();
+ . RETURN_ERROR (MIX_PERR_INV_ADDRESS, yytext);
+}
+
+
+<INDEX>{
+ {number}[\n(\t ] {
+ int end = yytext[yyleng-1];
+ ins.index = mix_byte_new (atol (yytext));
+ if ( end == '\n' )
+ ADD_INS ();
+ else if ( end == '(' )
+ BEGIN (FSPEC);
+ else
+ { /* eat rest of line (comment) */
+ while ( (end = input()) != '\n' && end != EOF ) ;
+ if ( end == '\n' ) ADD_INS ();
+ else RETURN_ERROR (MIX_PERR_UNEX_EOF, NULL);
+ }
+ }
+ {expr}/[\n(\t ] ENTER_EVAL ();
+ \n {
+ mix_parser_log_error (parser, MIX_PERR_INV_IDX, lineno++, NULL, FALSE);
+ RESET ();
+ BEGIN (INITIAL);
+ }
+ . RETURN_ERROR (MIX_PERR_INV_IDX, yytext);
+}
+
+<FSPEC>{
+ {number}")"(({ws}+.*\n)|\n) {
+ glong val = atol (yytext);
+ if ( val < 0 || val > MIX_BYTE_MAX )
+ RETURN_ERROR (MIX_PERR_INV_FSPEC, NULL);
+ if ( ins.opcode != mix_opMOVE
+ && ( ins.opcode < mix_opJBUS || ins.opcode > mix_opJXx )
+ && !mix_fspec_is_valid (mix_byte_new (val)) )
+ RETURN_ERROR (MIX_PERR_INV_FSPEC, NULL);
+ if ( nof )
+ mix_parser_log_error (parser, MIX_PERR_INV_FSPEC,
+ lineno, _("ignored"), TRUE);
+ else
+ {
+ ins.fspec = mix_byte_new (val);
+ ADD_INS ();
+ }
+ }
+ {expr}/")" {
+ ENTER_EVAL ();
+ }
+ . RETURN_ERROR (MIX_PERR_INV_FSPEC, yytext);
+}
+
+
+<EVAL>{
+ {binop}{digit}+ {
+ const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1;
+ mix_word_t value = mix_word_new (atol (s));
+ expr_val = eval_binop_ (yytext, expr_val, value);
+ }
+ {binop}{symbol} {
+ const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1;
+ if ( !mix_symbol_table_is_defined (parser->symbol_table, s) ) {
+ mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, lineno, s, FALSE);
+ yy_pop_state ();
+ }
+ expr_val = eval_binop_ (yytext, expr_val,
+ mix_symbol_table_value (parser->symbol_table, s));
+ }
+ {binop}"*" {
+ expr_val = eval_binop_ (yytext, expr_val,
+ mix_short_to_word_fast (parser->loc_count));
+ }
+ "*" unput_word_ (mix_short_to_word_fast (parser->loc_count));
+ {number} expr_val = mix_word_new (atol (yytext));
+ {symbol} {
+ if ( !mix_symbol_table_is_defined (parser->symbol_table, yytext) ) {
+ mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, lineno, yytext, FALSE);
+ yy_pop_state ();
+ }
+ expr_val = mix_symbol_table_value (parser->symbol_table, yytext);
+ }
+ [,)(=\n\t ] unput (yytext[0]); unput_word_ (expr_val); yy_pop_state ();
+ . RETURN_ERROR (MIX_PERR_INV_EXPR, yytext);
+}
+
+<WEVAL>{
+ {number}"(" {
+ is_fp = TRUE;
+ wexpr_val_tmp = mix_word_new (atol (yytext));
+ }
+ {number}")" {
+ glong val = atol (yytext);
+ if ( !is_fp ) {
+ mix_parser_log_error (parser, MIX_PERR_MIS_PAREN, lineno, NULL, FALSE);
+ yy_pop_state ();
+ }
+ if ( val < 0 || val > MIX_BYTE_MAX
+ || !mix_fspec_is_valid (mix_byte_new (val)) ) {
+ mix_parser_log_error (parser, MIX_PERR_INV_FSPEC, lineno, NULL, FALSE);
+ yy_pop_state ();
+ }
+ is_fp = FALSE;
+ wexpr_val = mix_word_store_field (mix_byte_new (val), wexpr_val_tmp,
+ wexpr_val);
+ }
+ {number}/[,()\n\t ] wexpr_val = mix_word_new (atol (yytext));
+ {expr}/[,()\n\t ] ENTER_EVAL ();
+ ,/{expr} /* eat comma if followed by expression */
+ [\n\t ] { /* ok if not inside an f-part */
+ if ( is_fp ) {
+ mix_parser_log_error (parser, MIX_PERR_MIS_PAREN, lineno, NULL, FALSE);
+ yy_pop_state ();
+ }
+ unput (yytext[yyleng-1]);
+ unput_word_ (wexpr_val);
+ yy_pop_state ();
+ }
+ . RETURN_ERROR (MIX_PERR_INV_EXPR, NULL);
+}
+
+%%
+
+static mix_word_t
+eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y)
+{
+ mix_word_t result = MIX_WORD_ZERO;
+ switch (op[0])
+ {
+ case '+':
+ result = mix_word_add (x,y);
+ break;
+ case '-':
+ result = mix_word_sub (x,y);
+ break;
+ case '*':
+ mix_word_mul (x, y, NULL, &result);
+ break;
+ case ':':
+ {
+ mix_word_t a;
+ mix_word_mul (x, 8, NULL, &a);
+ result = mix_word_add (a, y);
+ break;
+ }
+ case '/':
+ if ( strlen (op) > 1 && op[1] == '/' ) {
+ mix_word_div (x,MIX_WORD_ZERO,y, &result, NULL);
+ } else {
+ mix_word_div (MIX_WORD_ZERO, x, y, &result, NULL);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ return result;
+}
+
+
+static void
+unput_word_ (mix_word_t word)
+{
+ gchar *value;
+ gint k;
+ value = g_strdup_printf ("%s%ld",
+ mix_word_is_negative (word)? "-":"+",
+ mix_word_magnitude (word));
+ for (k = strlen (value) - 1; k >= 0; --k)
+ unput (value[k]);
+ g_free (value);
+}
diff --git a/mixlib/mix_src_file.c b/mixlib/mix_src_file.c
new file mode 100644
index 0000000..4e1489b
--- /dev/null
+++ b/mixlib/mix_src_file.c
@@ -0,0 +1,157 @@
+/* -*-c-*- -------------- mix_src_file.c :
+ * Implementation of the functions declared in mix_src_file.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/10 15:23:46 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "mix_src_file.h"
+
+/* the MIXAL source file type */
+struct mix_src_file_t
+{
+ gchar *path; /* the path to the disk file */
+ GPtrArray *lines; /* an array of the file lines */
+ guint lineno; /* the number of lines */
+};
+
+/* format a source line */
+static gchar *
+format_line_ (gchar *line)
+{
+ const gchar *label, *op, *rest;
+ gint k = 0;
+
+ if (!line) return line;
+ if (line[0] == '*' || strlen(line) == 0)
+ return g_strdup (line);
+
+ if (isspace (line[0]))
+ {
+ label = " ";
+ while (line[k] && isspace (line[k])) ++k;
+ }
+ else
+ {
+ label = line;
+ while (line[k] && !isspace (line[k])) ++k;
+ while (line[k] && isspace (line[k])) ++k;
+ }
+
+ if (line[k])
+ {
+ line[k - 1] = 0;
+ op = line + k;
+ while (line[k] && !isspace (line[k])) ++k;
+ while (line[k] && isspace (line[k])) ++k;
+ line[k - 1] = 0;
+ rest = (line[k]) ? line + k: "";
+ }
+ else
+ {
+ op = rest = "";
+ }
+
+
+ return g_strdup_printf ("%-11s %-5s %s", label, op, rest);
+}
+
+/* load the source file lines into memory */
+static gboolean
+load_file_ (mix_src_file_t *file)
+{
+ mix_file_t *mf = mix_file_new_with_def_ext (file->path,
+ mix_io_READ,
+ MIX_SRC_DEFEXT);
+ if (mf != NULL)
+ {
+ enum {BUFFER_SIZE = 256};
+ static gchar BUFFER[BUFFER_SIZE];
+
+ FILE *f = mix_file_to_FILE (mf);
+ file->lines = g_ptr_array_new ();
+ file->lineno = 0;
+
+ while (fgets (BUFFER, BUFFER_SIZE, f) == BUFFER)
+ {
+ g_ptr_array_add (file->lines, (gpointer) format_line_ (BUFFER));
+ file->lineno++;
+ }
+
+ mix_file_delete (mf);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* create a new src file from an existing disk file */
+mix_src_file_t *
+mix_src_file_new_for_read (const gchar *path)
+{
+ mix_src_file_t *result = g_new (mix_src_file_t, 1);
+ result->lines = NULL;
+ result->path = g_strdup (path);
+ result->lineno = 0;
+ return result;
+}
+
+/* destroy a src file object */
+void
+mix_src_file_delete (mix_src_file_t *src)
+{
+ g_return_if_fail (src != NULL);
+ if (src->lines) g_ptr_array_free (src->lines, TRUE);
+ g_free (src->path);
+ g_free (src);
+}
+
+/* get the source file path */
+const gchar *
+mix_src_file_get_path (const mix_src_file_t *src)
+{
+ g_return_val_if_fail (src != NULL, NULL);
+ return src->path;
+}
+
+/* get a given line of the source file */
+const gchar *
+mix_src_file_get_line (const mix_src_file_t *src, guint lineno)
+{
+ g_return_val_if_fail (src != NULL, NULL);
+ if (src->lines == NULL && !load_file_ ((mix_src_file_t*)src))
+ return NULL;
+ if (lineno > src->lineno || lineno == 0)
+ return NULL;
+ return (gchar *)g_ptr_array_index (src->lines, lineno - 1);
+}
+
+/* get the total no. of lines in the file */
+guint
+mix_src_file_get_line_no (const mix_src_file_t *src)
+{
+ g_return_val_if_fail (src != NULL, 0);
+ if (src->lines == NULL && !load_file_ ((mix_src_file_t*)src))
+ return 0;
+ return src->lineno;
+}
+
diff --git a/mixlib/mix_src_file.h b/mixlib/mix_src_file.h
new file mode 100644
index 0000000..1392df2
--- /dev/null
+++ b/mixlib/mix_src_file.h
@@ -0,0 +1,57 @@
+/* -*-c-*- ---------------- mix_src_file.h :
+ * Declaration of mix_src_file_t, a type representing a MIXAL source
+ * file.
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/02/20 00:23:58 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_SRC_FILE_H
+#define MIX_SRC_FILE_H
+
+#include "mix_file.h"
+
+/* the MIXAL source file type */
+typedef struct mix_src_file_t mix_src_file_t;
+
+/* create a new src file from an existing disk file */
+extern mix_src_file_t *
+mix_src_file_new_for_read (const gchar *path);
+
+/* destroy a src file object */
+extern void
+mix_src_file_delete (mix_src_file_t *src);
+
+/* get the source file path */
+extern const gchar *
+mix_src_file_get_path (const mix_src_file_t *src);
+
+/* get a given line of the source file */
+extern const gchar *
+mix_src_file_get_line (const mix_src_file_t *src, guint lineno);
+
+/* get the total no. of lines in the file */
+extern guint
+mix_src_file_get_line_no (const mix_src_file_t *src);
+
+
+
+#endif /* MIX_SRC_FILE_H */
+
diff --git a/mixlib/mix_symbol_table.c b/mixlib/mix_symbol_table.c
new file mode 100644
index 0000000..33874ea
--- /dev/null
+++ b/mixlib/mix_symbol_table.c
@@ -0,0 +1,196 @@
+/* -*-c-*- -------------- mix_symbol_table.c :
+ * Implementation of the functions declared in mix_symbol_table.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <ctype.h> /* isdigit */
+#include "mix_symbol_table.h"
+
+/* Create an empty table */
+mix_symbol_table_t *
+mix_symbol_table_new(void)
+{
+ return g_hash_table_new(g_str_hash, g_str_equal);
+}
+
+/* Create a table and populate it with the contents of a table stored
+ in -file- using mix_symbol_table_print(table, MIX_SYM_LINE, file)
+*/
+mix_symbol_table_t *
+mix_symbol_table_new_from_file(FILE *file)
+{
+ mix_symbol_table_t *result = mix_symbol_table_new();
+ if ( result != NULL )
+ {
+ gchar sym[MIX_SYM_MAX_LEN + 1];
+ glong val;
+
+ while ( getc(file) == ',' )
+ {
+ if ( fscanf(file, "%s =%ld", sym, &val) != EOF )
+ mix_symbol_table_add(result, sym, mix_word_new(val));
+ }
+ }
+ return result;
+}
+
+/* Delete a table */
+static void
+delete_hash_keys_(gpointer key, gpointer value, gpointer data)
+{
+ g_free(key);
+}
+
+void
+mix_symbol_table_delete(mix_symbol_table_t *table)
+{
+ g_hash_table_foreach(table, delete_hash_keys_, NULL);
+ g_hash_table_destroy(table);
+}
+
+/* add/remove symbols from other table */
+static void
+add_symbol_(gpointer symbol, gpointer value, gpointer target)
+{
+ mix_symbol_table_t *t = (mix_symbol_table_t *)target;
+ gchar *s = (gchar *)symbol;
+ mix_word_t v = mix_word_new(GPOINTER_TO_UINT(value));
+ mix_symbol_table_insert (t, s, v);
+}
+
+static void
+remove_symbol_(gpointer symbol, gpointer value, gpointer target)
+{
+ mix_symbol_table_t *t = (mix_symbol_table_t *)target;
+ gchar *s = (gchar *)symbol;
+ mix_symbol_table_remove (t, s);
+}
+
+gboolean
+mix_symbol_table_merge_table (mix_symbol_table_t *table,
+ const mix_symbol_table_t *from)
+{
+ g_return_val_if_fail (table != NULL, FALSE);
+ if (from != NULL)
+ {
+ mix_symbol_table_foreach ((gpointer)from, add_symbol_, table);
+ }
+ return TRUE;
+}
+
+gboolean
+mix_symbol_table_substract_table (mix_symbol_table_t *table,
+ const mix_symbol_table_t *other)
+{
+ g_return_val_if_fail (table != NULL, FALSE);
+ if (other != NULL)
+ {
+ mix_symbol_table_foreach ((gpointer)other, remove_symbol_, table);
+ }
+ return TRUE;
+}
+
+
+/* Add/remove symbols one by one */
+gint
+mix_symbol_table_add(mix_symbol_table_t *table,
+ const gchar *sym, mix_word_t value)
+{
+ gpointer key, val;
+
+ if ( table == NULL || sym == NULL ) return MIX_SYM_FAIL;
+ if ( strlen(sym) > MIX_SYM_MAX_LEN ) return MIX_SYM_LONG;
+
+ if ( !g_hash_table_lookup_extended(table, sym, &key, &val) )
+ {
+ key = g_strdup(sym);
+ g_hash_table_insert(table, key, (gpointer)value);
+ return MIX_SYM_OK;
+ }
+ else
+ return MIX_SYM_DUP;
+}
+
+/* Add or modify symbol if it exists */
+gint
+mix_symbol_table_insert(mix_symbol_table_t *table,
+ const gchar *sym, mix_word_t new_value)
+{
+ gpointer key, val;
+
+ if ( table == NULL || sym == NULL ) return MIX_SYM_FAIL;
+ if ( strlen(sym) > MIX_SYM_MAX_LEN ) return MIX_SYM_LONG;
+
+ if ( !g_hash_table_lookup_extended(table, sym, &key, &val) )
+ key = g_strdup(sym);
+ g_hash_table_insert(table, key, (gpointer)new_value);
+ return MIX_SYM_OK;
+}
+
+
+/* Symbols lookup */
+gboolean
+mix_symbol_table_is_defined(const mix_symbol_table_t *table, const gchar *sym)
+{
+ gpointer key, val;
+ return g_hash_table_lookup_extended((GHashTable *)table, sym, &key, &val);
+}
+
+/* Print table */
+#define is_local_sym_(sym) \
+ ((sym) && (strlen(sym)==2) && (sym[1] == 'B') && isdigit(sym[0]))
+
+static gboolean skip_ = FALSE;
+
+static void
+print_sym_rows_(gpointer symbol, gpointer value, gpointer file)
+{
+ char *s = (char *)symbol;
+ if (skip_ && !is_local_sym_(s)) {
+ mix_word_t word = (mix_word_t)GPOINTER_TO_UINT(value);
+ fprintf((FILE *)file, "%s: %s%ld\n", s,
+ mix_word_is_negative(word)? "-":"",
+ mix_word_magnitude(word));
+ }
+}
+
+static void
+print_sym_line_(gpointer symbol, gpointer value, gpointer file)
+{
+ char *s = (char *)symbol;
+ if (skip_ && !is_local_sym_(s)) {
+ mix_word_t word = (mix_word_t)GPOINTER_TO_UINT(value);
+ fprintf((FILE *)file, ",%s =%s%ld", s,
+ mix_word_is_negative(word)? "-":"",
+ mix_word_magnitude(word));
+ }
+}
+
+void
+mix_symbol_table_print(const mix_symbol_table_t *table, gint mode,
+ FILE *file, gboolean skiplocal)
+{
+ GHFunc func = (mode == MIX_SYM_LINE)? print_sym_line_ : print_sym_rows_;
+ skip_ = skiplocal;
+ if ( table != NULL )
+ g_hash_table_foreach((GHashTable *)table, func, (gpointer)file);
+ if ( mode == MIX_SYM_LINE ) putc(';', file); /* to mark end-of-table */
+}
+
+
diff --git a/mixlib/mix_symbol_table.h b/mixlib/mix_symbol_table.h
new file mode 100644
index 0000000..4a22444
--- /dev/null
+++ b/mixlib/mix_symbol_table.h
@@ -0,0 +1,109 @@
+/* -*-c-*- ---------------- mix_symbol_table.h :
+ * Type mix_symbol_table_t and functions to manipulate it.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_SYMBOL_TABLE_H
+#define MIX_SYMBOL_TABLE_H
+
+#include <stdio.h>
+#include "mix_types.h"
+
+/* A symbol table shall be implemented as a hash table */
+typedef GHashTable mix_symbol_table_t ;
+
+/* Maximum length of stored symbols */
+#define MIX_SYM_MAX_LEN 10
+
+/* Create an empty table */
+extern mix_symbol_table_t *
+mix_symbol_table_new (void);
+
+/* Create a table and populate it with the contents of a table stored
+ in -file- using mix_symbol_table_print (table, MIX_SYM_LINE, file)
+*/
+extern mix_symbol_table_t *
+mix_symbol_table_new_from_file (FILE *file);
+
+
+/* Delete a table */
+extern void
+mix_symbol_table_delete (mix_symbol_table_t *table);
+
+/* add/remove symbols from other table */
+extern gboolean
+mix_symbol_table_merge_table (mix_symbol_table_t *table,
+ const mix_symbol_table_t *from);
+
+extern gboolean
+mix_symbol_table_substract_table (mix_symbol_table_t *table,
+ const mix_symbol_table_t *other);
+
+/* Add/remove symbols one by one */
+/* possible outcomes: */
+enum {
+ MIX_SYM_FAIL, /* attempt failed */
+ MIX_SYM_OK,
+ MIX_SYM_DUP, /* duplicated symbol */
+ MIX_SYM_LONG /* symbol too long: only MIX_SYM_MAX_LEN chars used */
+};
+
+extern gint
+mix_symbol_table_add (mix_symbol_table_t *table,
+ const gchar *sym, mix_word_t value);
+
+#define mix_symbol_table_remove(table, sym) \
+ g_hash_table_remove (table, sym)
+
+
+/* Add or modify symbol if it exists */
+extern gint
+mix_symbol_table_insert (mix_symbol_table_t *table,
+ const gchar *sym, mix_word_t new_value);
+
+/* Add or modify symbol if it exists, without copiying sym */
+#define mix_symbol_table_insert_static(table,sym,value)\
+ g_hash_table_insert (table,(gpointer)sym,GUINT_TO_POINTER (value))
+
+/* Symbols lookup */
+extern gboolean
+mix_symbol_table_is_defined (const mix_symbol_table_t *table, const gchar *sym);
+
+#define mix_symbol_table_value(table,sym) \
+ (mix_word_t)GPOINTER_TO_UINT (g_hash_table_lookup ((GHashTable *)table, \
+ (gpointer)sym))
+
+/* Traverse the table */
+#define mix_symbol_table_foreach(table,func,data) \
+ g_hash_table_foreach (table,func,data)
+
+/* Print the table */
+enum {
+ MIX_SYM_ROWS, /* each symbol/value in a row */
+ MIX_SYM_LINE /* {,symbol =value}*; in a single row */
+};
+
+extern void
+mix_symbol_table_print (const mix_symbol_table_t *table, gint mode,
+ FILE *file, gboolean skiplocal);
+
+
+#endif /* MIX_SYMBOL_TABLE_H */
+
diff --git a/mixlib/mix_types.c b/mixlib/mix_types.c
new file mode 100644
index 0000000..40246cd
--- /dev/null
+++ b/mixlib/mix_types.c
@@ -0,0 +1,566 @@
+/* -*-c-*- ------------------ mix_types.c :
+ * Implementation file for mix_types.h declarations.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "mix.h"
+#include <limits.h>
+#include "mix_types.h"
+
+
+/*------------------------ initialisation stuff ------------------------*/
+/* flag telling whether a field spec is valid */
+static gboolean is_bad_field_[MIX_BYTE_MAX + 1];
+/* shift associated with a fspec */
+static guint shift_[MIX_BYTE_MAX + 1];
+/* mask associated with a fspec */
+static glong mask_[MIX_BYTE_MAX + 1];
+
+/* maps from gchar's to mix_char_t */
+#define NONP_ (guchar)('?')
+static mix_char_t ascii_to_mix_char_[UCHAR_MAX + 1];
+static guchar mix_char_to_ascii_[MIX_CHAR_MAX + 1] = {
+ ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'd', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 's', 'p', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6',
+ '7', '8', '9', '.', ',', '(', ')', '+', '-', '*', '/', '=', '$',
+ '<', '>', '@', ';', ':', '\''
+};
+
+
+/* initialise the above arrays */
+void
+mix_init_types (void)
+{
+ guint lt, rt;
+ for (lt = 0; lt < 8; ++lt)
+ for (rt = 0; rt < 8; ++rt)
+ {
+ guint F = 8 * lt + rt;
+ is_bad_field_[F] = rt < lt || 5 < rt;
+ if ( is_bad_field_[F] )
+ shift_[F] = 0, mask_[F] = 0;
+ else
+ {
+ guint width = rt - (lt == 0 ? 1 : lt) + 1;
+ shift_[F] = 6 * (5 - rt);
+ mask_[F] = ((1L << (6 * width)) - 1) << shift_[F];
+ }
+ }
+
+ for ( lt = 0; lt < UCHAR_MAX + 1; ++lt )
+ ascii_to_mix_char_[lt] = NONP_;
+ for ( lt = 0; lt < MIX_CHAR_MAX + 1; ++lt )
+ ascii_to_mix_char_[mix_char_to_ascii_[lt]] = (guchar)lt;
+}
+
+mix_char_t
+mix_ascii_to_char (guchar c)
+{
+ return ascii_to_mix_char_[c];
+}
+
+
+guchar
+mix_char_to_ascii (mix_char_t c)
+{
+ return c > MIX_CHAR_MAX ? NONP_ : mix_char_to_ascii_[c];
+}
+
+
+/*---------------------------- m_word_t --------------------------------- */
+
+/* Create mix_word_t from an array of mix_byte_t */
+mix_word_t
+mix_bytes_to_word (mix_byte_t *bytes, guint byteno)
+{
+ mix_word_t result = 0;
+ guint k;
+
+ g_return_val_if_fail (bytes != NULL, MIX_WORD_ZERO);
+ g_return_val_if_fail (byteno != 0, MIX_WORD_ZERO);
+
+ if ( byteno > 5 ) byteno = 5;
+ for ( k = 0; k < byteno; k++ )
+ result |= ((gulong)bytes[k]) << (6*(byteno-k-1));
+
+ return result;
+}
+
+
+/* Field operations */
+mix_word_t /* the specified field or 0 if f is not valid */
+mix_word_get_field (mix_fspec_t f, mix_word_t word)
+{
+ mix_word_t result;
+
+ g_return_val_if_fail (!is_bad_field_[f],MIX_WORD_ZERO);
+
+ result = ( (word & mask_[f]) >> shift_[f] );
+ if (f < 8) /* if f is of the form (0:R), retain the sign of word */
+ result |= mix_word_sign (word);
+
+ return result;
+}
+
+
+mix_word_t
+mix_word_set_field (mix_fspec_t f, mix_word_t from, mix_word_t to)
+{
+ mix_word_t result;
+ glong m = mask_[f];
+
+ g_return_val_if_fail (!is_bad_field_[f],to);
+
+ if (f < 8) /* if F is of the form (0:R), use the sign of -from- */
+ result = (to & ~m & ~MIX_WORD_SIGN_BIT)
+ | ((from /*<< shift_[f]*/) & m) | mix_word_sign (from);
+ else
+ result = (to & ~m) | ((from /*<< shift_[f]*/) & m);
+
+ return result;
+}
+
+mix_word_t
+mix_word_store_field (mix_fspec_t f, mix_word_t from, mix_word_t to)
+{
+ mix_word_t result;
+ glong m = mask_[f];
+
+ g_return_val_if_fail (!is_bad_field_[f],to);
+
+ if (f < 8) /* if F is of the form (0:R), use the sign of -from- */
+ result = (to & ~m & ~MIX_WORD_SIGN_BIT)
+ | ((from << shift_[f]) & m) | mix_word_sign (from);
+ else
+ result = (to & ~m) | ((from << shift_[f]) & m);
+
+ return result;
+}
+
+
+
+gboolean
+mix_fspec_is_valid (mix_fspec_t f)
+{
+ return !(is_bad_field_[f]);
+}
+
+mix_byte_t
+mix_word_get_byte (mix_word_t word, /* word parsed */
+ guint idx /* byte: 1 to 5 */ )
+{
+ mix_byte_t fspec = mix_fspec_new (idx,idx);
+
+ g_return_val_if_fail ((idx > 0 && idx < 6), MIX_BYTE_ZERO);
+
+ return mix_byte_new (mix_word_get_field (fspec,word));
+}
+
+
+extern void
+mix_word_set_byte (mix_word_t *into, guint idx, mix_byte_t value)
+{
+ mix_word_t from = value;
+ mix_byte_t fspec = mix_fspec_new (idx,idx);
+
+ g_return_if_fail (into != NULL);
+ g_return_if_fail (idx > 0 && idx < 6);
+
+ from <<= shift_[fspec];
+ *into = mix_word_set_field (fspec,from,*into);
+}
+
+/* Arithmetic operations */
+mix_word_t
+mix_word_add (mix_word_t x, mix_word_t y)
+{
+ static const gulong MIX_WORD_MAX_SIM = 2*MIX_WORD_MAX + 1;
+
+ gint32 result;
+ if ( mix_word_sign (x) == mix_word_sign (y) )
+ {
+ result = (mix_word_magnitude (x) + mix_word_magnitude (y));
+ if ( result > MIX_WORD_MAX ) {
+ /* for instance MIX_WORD_MAX + 1 = - MIX_WORD_MAX */
+ result = MIX_WORD_MAX_SIM - result;
+ result |= mix_word_sign (mix_word_negative (x));
+ } else if ( result != 0 )
+ result |= mix_word_sign (x);
+ /* keep positive sign for 0 so that w - w == -w + w */
+ }
+ else
+ {
+ result = mix_word_magnitude (x) - mix_word_magnitude (y);
+ if (result < 0)
+ result = -result|mix_word_sign (y);
+ else if (result > 0)
+ result = result|mix_word_sign (x);
+ /* keep positive sign for 0 so that w - w == -w + w */
+ }
+
+ g_assert ( result >= 0 );
+
+ return (mix_word_t)result;
+}
+
+gboolean /* TRUE if overflow */
+mix_word_add_and_carry (mix_word_t x, mix_word_t y,
+ mix_word_t *h, mix_word_t *l)
+{
+ gboolean result;
+
+ if ( mix_word_sign (x) == mix_word_sign (y) )
+ {
+ guint32 sum = (mix_word_magnitude (x) + mix_word_magnitude (y));
+ if ( sum > MIX_WORD_MAX )
+ {
+ result = TRUE;
+ if ( l != NULL )
+ {
+ *l = sum - MIX_WORD_MAX -1;
+ *l |= mix_word_sign (x);
+ }
+ if ( h != NULL )
+ {
+ *h = sum >> 30;
+ *h |= mix_word_sign (x);
+ }
+ }
+ else /* sum <= MIX_WORD_MAX */
+ {
+ result = FALSE;
+ if ( h != NULL ) *h = 0;
+ if ( l != NULL )
+ {
+ *l = sum;
+ if ( sum != 0 )
+ *l |= mix_word_sign (x);
+ /* keep positive sign for 0 so that w - w == -w + w */
+ }
+ }
+ }
+ else /* mix_word_sign (x) != mix_word_sign (y) */
+ {
+ result = FALSE;
+ if ( h != NULL ) *h = 0;
+ if ( l != NULL )
+ {
+ gint32 dif = mix_word_magnitude (x) - mix_word_magnitude (y);
+ if ( dif < 0)
+ *l = (-dif)|mix_word_sign (y);
+ else if ( dif > 0)
+ *l = dif|mix_word_sign (x);
+ else /* keep positive sign for 0 so that w - w == -w + w */
+ *l = MIX_WORD_ZERO;
+ }
+ }
+
+ return result;
+}
+
+
+void
+mix_word_mul (mix_word_t x, mix_word_t y,
+ mix_word_t *high_word, mix_word_t *low_word)
+{
+ guint32 sign = mix_word_sign (x) ^ mix_word_sign (y);
+
+ /*
+ x = x0 + x1 * 2 ^ 10 + x2 * 2 ^ 20
+ y = y0 + y1 * 2 ^ 10 + y2 * 2 ^ 20
+ x0, x1, x2, y0, y1, y2 are < 2 ^ 10
+ */
+ guint32 x0 = (x & 0x000003FF);
+ guint32 x1 = (x & 0x000FFC00) >> 10;
+ guint32 x2 = (x & 0x3FF00000) >> 20;
+ guint32 y0 = (y & 0x000003FF);
+ guint32 y1 = (y & 0x000FFC00) >> 10;
+ guint32 y2 = (y & 0x3FF00000) >> 20;
+
+ /*
+ x * y = partial0 +
+ partial1 * 2 ^ 10 +
+ partial2 * 2 ^ 20 +
+ partial3 * 2 ^ 30 +
+ partial4 * 2 ^ 40
+ partial0 and partial4 are < 2 ^ 20
+ partial1 and partial3 are < 2 ^ 21
+ partial2 is < 3 * 2 ^ 20
+ */
+ guint32 partial0 = x0 * y0;
+ guint32 partial1 = x0 * y1 + x1 * y0;
+ guint32 partial2 = x0 * y2 + x1 * y1 + x2 * y0;
+ guint32 partial3 = x1 * y2 + x2 * y1;
+ guint32 partial4 = x2 * y2;
+
+ /* sum1 has a place value of 1 and is < 2 ^ 32 */
+ guint32 sum1 = partial0 + (partial1 << 10);
+ guint32 carry1 = (sum1 & 0xFFF00000) >> 20;
+
+ /* sum2 has a place value of 2 ^ 20 and is < 2 ^ 32 */
+ guint32 sum2 = partial2 + (partial3 << 10) + carry1;
+ guint32 carry2 = (sum2 & 0xFFF00000) >> 20;
+
+ /* sum3 has a place value of 2 ^ 40 and is < 2 ^ 20 */
+ guint32 sum3 = partial4 + carry2;
+
+ sum1 &= ~0xFFF00000;
+ sum2 &= ~0xFFF00000;
+
+ /*
+ Now paste the three values back into two.
+ */
+ if ( low_word != NULL ) {
+ *low_word = sum1 | ((sum2 & 0x000003FF) << 20);
+ *low_word |= sign;
+ }
+ if ( high_word != NULL ) {
+ *high_word = ((sum2 & 0x000FFC00) >> 10) | (sum3 << 10);
+ *high_word |= sign;
+ }
+}
+
+
+gboolean
+mix_word_div (mix_word_t n1, mix_word_t n0, mix_word_t d,
+ mix_word_t *quotient, mix_word_t *remainder)
+{
+ gboolean overflow = FALSE;
+ long magn1 = mix_word_magnitude (n1);
+ long magd = mix_word_magnitude (d);
+
+ if (magd == 0)
+ {
+ overflow = TRUE;
+ /* just so they have -some- valid value */
+ if ( quotient != NULL ) *quotient = 0;
+ if ( remainder != NULL ) *remainder = 0;
+ }
+ else if (magn1 == 0)
+ { /* special-cased for speed */
+ if ( quotient != NULL )
+ *quotient = (mix_word_sign (n1) ^ mix_word_sign (d))
+ | (mix_word_magnitude (n0) / magd);
+ if ( remainder != NULL )
+ *remainder = mix_word_sign (n1) | (mix_word_magnitude (n0) % magd);
+ }
+ else if (magd <= magn1)
+ {
+ overflow = TRUE;
+ if ( quotient != NULL ) *quotient = 0;
+ if ( remainder != NULL ) *remainder = 0;
+ }
+ else
+ {
+ long q = mix_word_magnitude (n0);
+ long r = magn1;
+ unsigned i;
+ for (i = 30; i != 0; --i) {
+ r <<= 1;
+ if ( (q & (1L << 29)) != 0 )
+ ++r;
+ q = (q << 1) & ((1L << 30) - 1);
+ if (magd <= r)
+ ++q, r -= magd;
+ }
+ if ( quotient != NULL )
+ *quotient = (mix_word_sign (n1) ^ mix_word_sign (d)) | q;
+ if ( remainder != NULL )
+ *remainder = mix_word_sign(n1) | r;
+ }
+ return overflow;
+}
+
+void
+mix_word_shift_right (mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX)
+{
+ if ( pX != NULL ) *pX = mix_word_sign (X);
+ if ( pA != NULL ) *pA = mix_word_sign (A);
+ if (count < 5) {
+ if ( pA != NULL )
+ *pA |= mix_word_magnitude (A) >> (6 * count);
+ if ( pX != NULL )
+ *pX |= MIX_WORD_MAX & ( (mix_word_magnitude (X) >> (6 * count))
+ | (A << (30 - 6 * count)) );
+ } else if (count < 10 && pX != NULL)
+ *pX |= mix_word_magnitude (A) >> (6 * count - 30);
+ else
+ ;
+}
+
+
+void
+mix_word_shift_left (mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX)
+{
+ if ( pX != NULL ) *pX = mix_word_sign (X);
+ if ( pA != NULL ) *pA = mix_word_sign (A);
+ if (count < 5) {
+ if ( pX != NULL ) *pX |= MIX_WORD_MAX & (X << (6 * count));
+ if ( pA != NULL )
+ *pA |= MIX_WORD_MAX & ( (A << (6 * count)) |
+ (mix_word_magnitude (X) >> (30 - 6 * count)) );
+ } else if (count < 10 && pA != NULL)
+ *pA |= MIX_WORD_MAX & (X << (6 * count - 30));
+ else
+ ;
+}
+
+void
+mix_word_shift_left_circular (mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX)
+{
+ mix_word_t A1, X1;
+ guint c;
+
+ count %= 10;
+ A1 = count < 5 ? A : X;
+ X1 = count < 5 ? X : A;
+ c = 6 * (count < 5 ? count : count - 5);
+ if ( pX != NULL )
+ *pX = mix_word_sign (X)
+ | ( MIX_WORD_MAX & (X1 << c) ) | ( mix_word_magnitude (A1) >> (30 - c) );
+ if ( pA != NULL )
+ *pA = mix_word_sign (A)
+ | ( MIX_WORD_MAX & (A1 << c) ) | ( mix_word_magnitude (X1) >> (30 - c) );
+}
+
+void
+mix_word_shift_right_circular (mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX)
+{
+ mix_word_t A1, X1;
+ guint c;
+
+ count %= 10;
+ A1 = count < 5 ? A : X;
+ X1 = count < 5 ? X : A;
+ c = 6 * (count < 5 ? count : count - 5);
+ if ( pX != NULL )
+ *pX = mix_word_sign (X)
+ | ( mix_word_magnitude (X1) >> c ) | ( MIX_WORD_MAX & (A1 << (30 - c)) );
+ if ( pA != NULL )
+ *pA = mix_word_sign (A)
+ | ( mix_word_magnitude (A1) >> c ) | ( MIX_WORD_MAX & (X1 << (30 - c)) );
+}
+
+
+/* Printable representation */
+void
+mix_word_print_to_file (mix_word_t word, const char *message, FILE *f)
+{
+ guint k;
+ if ( message ) fprintf (f, "%s ", message);
+ fprintf (f, "%s ", mix_word_sign (word) == 0 ? "+" : "-");
+ for ( k = 1; k < 6; ++k ) {
+ fprintf (f, "%02d ", mix_word_get_byte (word,k));
+ }
+ fprintf (f, "(%010ld)", mix_word_magnitude (word));
+}
+
+void
+mix_word_print_to_buffer (mix_word_t word, gchar *buf)
+{
+ g_return_if_fail (buf != NULL);
+ sprintf (buf, "%s %02d %02d %02d %02d %02d",
+ mix_word_sign (word) == 0 ? "+" : "-",
+ mix_word_get_byte (word, 1),
+ mix_word_get_byte (word, 2),
+ mix_word_get_byte (word, 3),
+ mix_word_get_byte (word, 4),
+ mix_word_get_byte (word, 5));
+}
+
+/* Conversions between words and shorts */
+mix_short_t
+mix_word_to_short (mix_word_t word)
+{
+ if ( mix_word_is_negative (word) )
+ return ( (word & MIX_SHORT_MAX) | MIX_SHORT_SIGN_BIT );
+ else
+ return (word & MIX_SHORT_MAX);
+}
+
+mix_word_t
+mix_short_to_word (mix_short_t s)
+{
+ if ( mix_short_is_negative (s) )
+ return ((mix_word_t) (mix_short_magnitude (s) | MIX_WORD_SIGN_BIT));
+ else
+ return ((mix_word_t)s);
+}
+
+mix_short_t
+mix_short_add (mix_short_t x, mix_short_t y)
+{
+ static const guint16 MIX_SHORT_MAX_SIM = 2*MIX_SHORT_MAX + 1;
+
+ gint16 result;
+ if ( mix_short_sign (x) == mix_short_sign (y) )
+ {
+ result = (mix_short_magnitude (x) + mix_short_magnitude (y));
+ if ( result > MIX_SHORT_MAX ) {
+ /* for instance MIX_SHORT_MAX + 1 = - MIX_SHORT_MAX */
+ result = MIX_SHORT_MAX_SIM - result;
+ result |= mix_short_sign (mix_short_negative (x));
+ } else if ( result != 0 )
+ result |= mix_short_sign (x);
+ /* keep positive sign for 0 so that w - w == -w + w */
+ }
+ else
+ {
+ result = mix_short_magnitude (x) - mix_short_magnitude (y);
+ if (result < 0)
+ result = -result|mix_short_sign (y);
+ else if (result > 0)
+ result = result|mix_short_sign (x);
+ /* keep positive sign for 0 so that w - w == -w + w */
+ }
+
+ g_assert ( result >= 0 );
+
+ return (mix_short_t)result;
+}
+
+
+/* Printable representation */
+void
+mix_short_print (mix_short_t s, const gchar *message)
+{
+ if ( message ) g_print ("%s ", message);
+ g_print ("%s ", mix_short_sign (s) == 0 ? "+" : "-");
+ g_print ("%02d %02d ", mix_byte_new (s>>6), mix_byte_new (s));
+ g_print ("(%04d)", mix_short_magnitude (s));
+}
+
+void
+mix_short_print_to_buffer (mix_short_t s, gchar *buf)
+{
+ g_return_if_fail (buf != NULL);
+ sprintf (buf, "%s %02d %02d",
+ mix_short_sign (s) == 0 ? "+" : "-",
+ mix_byte_new (s>>6), mix_byte_new (s));
+ /* g_print ("(%04d)", mix_short_magnitude (s));*/
+}
+
+
+
+
diff --git a/mixlib/mix_types.h b/mixlib/mix_types.h
new file mode 100644
index 0000000..918046e
--- /dev/null
+++ b/mixlib/mix_types.h
@@ -0,0 +1,291 @@
+/* -*-c-*- --------------- mix_types.h:
+ * This file contains declarations for the basic types used in MIX:
+ * mix_byte_t, mix_char_t, mix_short_t and mix_word_t.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_TYPES_H
+#define MIX_TYPES_H
+
+#include <stdio.h>
+#include "mix.h"
+
+/* Initialisation function to be called before using the other
+ * functions in this file
+ */
+extern void
+mix_init_types(void);
+
+
+/*----------------- m_byte_t --------------------------------------------*/
+/* MIX byte type */
+typedef guint8 mix_byte_t;
+
+/* Maximum value stored in an mix_byte_t */
+#define MIX_BYTE_MAX ((1L << 6) - 1)
+
+/* Zero mix byte */
+#define MIX_BYTE_ZERO ((mix_byte_t)0)
+
+/* Create a mix_byte_t from any native type */
+#define mix_byte_new(x) ((mix_byte_t)((x) & MIX_BYTE_MAX ))
+
+/* Operations */
+/* Addition */
+#define mix_byte_add(x,y) mix_byte_new((x) + (y))
+/* Substraction */
+#define mix_byte_sub(x,y) mix_byte_new((x) - (y))
+/* Product */
+#define mix_byte_mul(x,y) mix_byte_new((x) * (y))
+/* Quotient */
+#define mix_byte_div(x,y) mix_byte_new((x) / (y))
+
+
+/*----------------- mix_char_t --------------------------------------------*/
+/* MIX char type: chars are coded in MIX from 0 to MIX_CHAR_MAX */
+typedef guint8 mix_char_t;
+
+#define MIX_CHAR_MAX 55
+
+/* Conversions for mix_char_t's */
+#define mix_char_to_byte(mchar) mix_byte_new(mchar)
+#define mix_byte_to_char(byte) ((mix_char_t)(byte&MIX_CHAR_MAX))
+
+extern mix_char_t
+mix_ascii_to_char(guchar c);
+
+extern guchar
+mix_char_to_ascii(mix_char_t c);
+
+
+/*----------------- mix_word_t --------------------------------------------*/
+/*
+ * Represented as a gint32 (glib ensures that this type has 32
+ * bits). Bit 30 is the sign, higher bits are 0,
+ * and bits 0-29 are the magnitude.
+ * Each MIX 'byte' is a 6-bit substring of the magnitude.
+ */
+typedef guint32 mix_word_t;
+
+/* Maximum value stored in an mix_word_t */
+#define MIX_WORD_MAX ((1L << 30) - 1)
+/* Sign bit in a word */
+#define MIX_WORD_SIGN_BIT (1L << 30)
+/* Zero mix word */
+#define MIX_WORD_ZERO ((mix_word_t)0)
+/* Negative zero mix word */
+#define MIX_WORD_MINUS_ZERO (MIX_WORD_ZERO | MIX_WORD_SIGN_BIT)
+
+
+/* Create a mix_word_t from any native type */
+#define mix_word_new(x) \
+( (x) < 0 \
+ ? ( MIX_WORD_SIGN_BIT | ((mix_word_t)(-(x)) & MIX_WORD_MAX) ) \
+ : ( (mix_word_t)(x) & MIX_WORD_MAX ) \
+)
+
+/* Create a mix_word_t from individual bytes */
+#define mix_word_new_b(b1,b2,b3,b4,b5) \
+((mix_word_t)(mix_byte_new(b5) + (mix_byte_new(b4)<<6) + \
+ (mix_byte_new(b3)<<12) + (mix_byte_new(b2)<<18) + \
+ (mix_byte_new(b1)<<24)))
+
+/* Create a negative mix_word_t from individual bytes */
+#define mix_word_new_bn(b1,b2,b3,b4,b5) \
+ mix_word_negative(mix_word_new_b(b1,b2,b3,b4,b5))
+
+/* Create mix_word_t from an array of mix_byte_t */
+extern mix_word_t
+mix_bytes_to_word(mix_byte_t *bytes, guint byteno);
+
+/* Access byte within a word */
+extern mix_byte_t /* byte -idx- or MIX_BYTE_ZERO if -idx- out of range */
+mix_word_get_byte(mix_word_t word, /* word parsed */
+ guint idx /* byte: 1 to 5 */);
+
+/* Set a byte within a mix_word_t */
+extern void
+mix_word_set_byte(mix_word_t *into, /* word to be modified */
+ guint idx, /* byte: 1 to 5 */
+ mix_byte_t value /* byte's value */);
+
+
+/* Operations */
+/* Sign-related definitions */
+#define mix_word_negative(word) ( (word) ^ MIX_WORD_SIGN_BIT )
+#define mix_word_reverse_sign(word) ( word ^= MIX_WORD_SIGN_BIT )
+#define mix_word_sign(word) ( (word) & MIX_WORD_SIGN_BIT )
+#define mix_word_magnitude(word) ( (word) & (MIX_WORD_SIGN_BIT - 1) )
+#define mix_word_is_positive(word) ( mix_word_sign(word) == 0 )
+#define mix_word_is_negative(word) ( mix_word_sign(word) != 0 )
+
+
+/* Arithmetic operations */
+extern mix_word_t
+mix_word_add(mix_word_t x, mix_word_t y);
+
+#define mix_word_sub(x,y) ( mix_word_add((x),mix_word_negative(y)) )
+
+/* Add two words filling a high word if needed.
+ -high_word- and/or -low_word- can be NULL.
+*/
+extern gboolean /* TRUE if overflow */
+mix_word_add_and_carry(mix_word_t x, mix_word_t y,
+ mix_word_t *high_word, mix_word_t *low_word);
+
+/* Product, stored in -high_word- and -low_word-, which
+ can be NULL.
+*/
+extern void
+mix_word_mul(mix_word_t x, mix_word_t y,
+ mix_word_t *high_word, mix_word_t *low_word);
+
+/* Division. -quotient- and/or -remainder- can be NULL. */
+extern gboolean /* TRUE if overflow */
+mix_word_div(mix_word_t n1, mix_word_t n0, mix_word_t d,
+ mix_word_t *quotient, mix_word_t *remainder);
+
+/* Shift operations */
+extern void
+mix_word_shift_left(mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX);
+extern void
+mix_word_shift_right(mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX);
+extern void
+mix_word_shift_left_circular(mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX);
+extern void
+mix_word_shift_right_circular(mix_word_t A, mix_word_t X, gulong count,
+ mix_word_t *pA, mix_word_t *pX);
+
+
+
+
+/*
+ * Fields within a word: a word containing the (L:R)
+ * bytes of the original one. L and R (with 0 <= L <= R < 6)
+ * are specified by a mix_fspec_t F = 8*L + R.
+ */
+typedef guint8 mix_fspec_t;
+
+#define mix_fspec_left(f) ( ((f)>>3) & 7 )
+#define mix_fspec_right(f) ( (f) & 7 )
+#define mix_fspec_new(L,R) ( mix_byte_new(8*(L) + (R)) )
+
+extern gboolean
+mix_fspec_is_valid(mix_fspec_t f);
+
+extern mix_word_t /* the specified field or 0 if f is not valid */
+mix_word_get_field(mix_fspec_t f, mix_word_t word);
+
+extern mix_word_t /* -to- with the field -f- from -from- or -to-
+ if -f- is not a valid fspec */
+mix_word_set_field(mix_fspec_t f, mix_word_t from, mix_word_t to);
+
+/* set field into a zero word */
+#define mix_word_extract_field(fspec,from_word) \
+ mix_word_set_field(fspec,from_word,MIX_WORD_ZERO)
+
+/* Store operation: the no. of bytes determined by -f- is taken
+ * from the right of -from- and stored into -to- in the location
+ * specified by -f-
+ */
+extern mix_word_t
+mix_word_store_field(mix_fspec_t f, mix_word_t from, mix_word_t to);
+
+
+/* Printable representation */
+#define mix_word_print(word,message) \
+ mix_word_print_to_file (word, message, stdout)
+
+extern void
+mix_word_print_to_file (mix_word_t word, const char *message, FILE *f);
+
+extern void
+mix_word_print_to_buffer (mix_word_t word, gchar *buf);
+
+
+/*----------------- mix_short_t ------------------------------------------*/
+typedef guint16 mix_short_t;
+
+#define MIX_SHORT_MAX ((1L << 12) - 1)
+#define MIX_SHORT_SIGN_BIT ((mix_short_t)(1L << 12))
+#define MIX_SHORT_ZERO ((mix_short_t)0)
+#define MIX_SHORT_MINUS_ZERO (MIX_SHORT_ZERO | MIX_SHORT_SIGN_BIT)
+
+/* Sign-related definitions */
+#define mix_short_negative(s) ( (s) ^ MIX_SHORT_SIGN_BIT )
+#define mix_short_sign(s) ( (s) & MIX_SHORT_SIGN_BIT )
+#define mix_short_magnitude(s) \
+ ( (s) & (MIX_SHORT_SIGN_BIT - 1) )
+#define mix_short_is_positive(s) ( mix_short_sign(s) == 0 )
+#define mix_short_is_negative(s) ( mix_short_sign(s) != 0 )
+
+/* create short from a long */
+#define mix_short_new(val) \
+ ((val)>= 0 ? (val)&MIX_SHORT_MAX : mix_short_negative(-(val)))
+
+/* Create shorts from individual bytes */
+#define mix_short_new_b(b1,b2) \
+((mix_short_t)((mix_byte_new(b1)<<6) + mix_byte_new(b2)))
+
+#define mix_short_new_bn(b1,b2) mix_short_negative(mix_short_new_b(b1,b2))
+
+/* Conversions between words and shorts. Arithmetic operations
+ on shorts are not provided but for addition: use words instead.
+*/
+/* Make a short taking word's sign and its two least significant
+ bytes (bytes no. 4 and 5)
+*/
+extern mix_short_t
+mix_word_to_short(mix_word_t word);
+
+extern mix_word_t
+mix_short_to_word(mix_short_t s);
+
+/* fast conversion (these macros' argument are evaluated twice */
+#define mix_word_to_short_fast(w) \
+( mix_word_is_negative(w) ? \
+ ((w) & MIX_SHORT_MAX)|MIX_SHORT_SIGN_BIT : (w)&MIX_SHORT_MAX )
+
+#define mix_short_to_word_fast(s) \
+( mix_short_is_negative(s) ? \
+(mix_word_t) (mix_short_magnitude(s)|MIX_WORD_SIGN_BIT): (mix_word_t)(s) )
+
+
+extern mix_short_t
+mix_short_add(mix_short_t x, mix_short_t y);
+
+
+/* printable representation */
+extern void
+mix_short_print(mix_short_t s, const gchar *message);
+
+extern void
+mix_short_print_to_buffer (mix_short_t s, gchar *buf);
+
+
+
+#endif /* MIX_TYPES_H */
+
+
+
+
diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c
new file mode 100644
index 0000000..9a39247
--- /dev/null
+++ b/mixlib/mix_vm.c
@@ -0,0 +1,562 @@
+/* -*-c-*- ------------------ mix_vm.c :
+ * Implementation of the functions declared in mix_vm.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "mix.h"
+#include "xmix_vm.h"
+
+static void
+vm_reset_ (mix_vm_t *vm)
+{
+ guint k;
+ set_rA_ (vm, MIX_WORD_ZERO);
+ set_rX_ (vm, MIX_WORD_ZERO);
+ set_rJ_ (vm, MIX_WORD_ZERO);
+ for ( k = 1; k < IREG_NO_+1; ++k )
+ set_rI_ (vm, k, MIX_WORD_ZERO);
+ set_over_ (vm, FALSE);
+ set_cmp_ (vm, mix_EQ);
+ set_loc_ (vm, MIX_WORD_ZERO);
+ for ( k = 0; k < MEM_CELLS_NO_; ++k)
+ set_cell_ (vm, k, MIX_WORD_ZERO);
+ halt_ (vm, FALSE);
+ if (vm->symbol_table != NULL )
+ {
+ mix_symbol_table_delete (vm->symbol_table);
+ vm->symbol_table = NULL;
+ }
+ if (vm->line_table != NULL)
+ {
+ g_tree_destroy (vm->line_table);
+ vm->line_table = NULL;
+ }
+ if (vm->address_table != NULL)
+ {
+ g_tree_destroy (vm->address_table);
+ vm->address_table = NULL;
+ }
+ if (vm->src_file != NULL)
+ {
+ mix_src_file_delete (vm->src_file);
+ vm->src_file = NULL;
+ }
+ bp_clear_all_ (vm);
+}
+
+
+/* Create/destroy a mix vm */
+mix_vm_t *
+mix_vm_new (void)
+{
+ int i;
+
+ mix_vm_t *vm = g_new (struct mix_vm_t,1);
+ vm->line_table = NULL;
+ vm->address_table = NULL;
+ vm->symbol_table = NULL;
+
+ for (i = 0; i < BD_NO_; ++i)
+ vm->devices[i] = NULL;
+
+ vm->clock = mix_vm_clock_new ();
+
+ vm_reset_ (vm);
+ return vm;
+}
+
+
+void
+mix_vm_delete (mix_vm_t * vm)
+{
+ int i;
+
+ g_return_if_fail (vm != NULL);
+
+ if (vm->line_table != NULL) g_tree_destroy (vm->line_table);
+ if (vm->address_table != NULL) g_tree_destroy (vm->address_table);
+ if (vm->symbol_table != NULL) mix_symbol_table_delete (vm->symbol_table);
+ if (vm->src_file != NULL) mix_src_file_delete (vm->src_file);
+ for (i = 0; i < BD_NO_; ++i)
+ mix_device_delete (vm->devices[i]);
+ mix_vm_clock_delete (vm->clock);
+ g_free (vm);
+}
+
+/* connect devices to a virtual machine */
+mix_device_t *
+mix_vm_connect_device (mix_vm_t *vm, mix_device_t *device)
+{
+ mix_device_t *old;
+ mix_device_type_t type;
+
+ g_return_val_if_fail (vm != NULL, NULL);
+ g_return_val_if_fail (device != NULL, NULL);
+
+ type = mix_device_type (device);
+ old = vm->devices[type];
+ vm->devices[type] = device;
+
+ return old;
+}
+
+/* Reset a vm (set state as of a newly created one) */
+void
+mix_vm_reset (mix_vm_t * vm)
+{
+ g_return_if_fail (vm != NULL);
+ vm_reset_ (vm);
+}
+
+/* Set start address for execution */
+void
+mix_vm_set_start_addr (mix_vm_t *vm, mix_address_t addr)
+{
+ g_return_if_fail (vm != NULL);
+ set_loc_ (vm, addr);
+}
+
+/* Access to the vm's registers */
+mix_word_t
+mix_vm_get_rA (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, MIX_WORD_ZERO);
+ return get_rA_ (vm);
+}
+
+mix_word_t
+mix_vm_get_rX (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, MIX_WORD_ZERO);
+ return get_rX_ (vm);
+}
+
+mix_short_t
+mix_vm_get_rJ (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, MIX_SHORT_ZERO);
+ return mix_word_to_short_fast (get_rJ_ (vm));
+}
+
+mix_short_t
+mix_vm_get_rI (const mix_vm_t *vm, guint idx)
+{
+ g_return_val_if_fail (vm != NULL, MIX_SHORT_ZERO);
+ g_return_val_if_fail (IOK_ (idx), MIX_SHORT_ZERO);
+ return mix_word_to_short_fast (get_rI_ (vm, idx));
+}
+
+void
+mix_vm_set_rA (mix_vm_t *vm, mix_word_t value)
+{
+ g_return_if_fail (vm != NULL);
+ set_rA_ (vm, value);
+}
+
+void
+mix_vm_set_rX (mix_vm_t *vm, mix_word_t value)
+{
+ g_return_if_fail (vm != NULL);
+ set_rX_ (vm, value);
+}
+
+void
+mix_vm_set_rJ (mix_vm_t *vm, mix_short_t value)
+{
+ g_return_if_fail (vm != NULL);
+ g_return_if_fail (mix_short_is_positive (value));
+ set_rJ_ (vm, mix_short_to_word_fast (value));
+}
+
+void
+mix_vm_set_rI (mix_vm_t *vm, guint idx, mix_short_t value)
+{
+ g_return_if_fail (vm != NULL);
+ g_return_if_fail (IOK_ (idx));
+ set_rI_ (vm, idx, mix_short_to_word_fast (value));
+}
+
+/* Access to the comparison flag and overflow toggle */
+mix_cmpflag_t
+mix_vm_get_cmpflag (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, mix_EQ);
+ return get_cmp_ (vm);
+}
+
+void
+mix_vm_set_cmpflag (mix_vm_t *vm, mix_cmpflag_t value)
+{
+ g_return_if_fail (vm != NULL);
+ set_cmp_ (vm, value);
+}
+
+gboolean
+mix_vm_get_overflow (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, TRUE);
+ return get_over_ (vm);
+}
+
+void
+mix_vm_set_overflow (mix_vm_t *vm, gboolean value)
+{
+ g_return_if_fail (vm != NULL);
+ set_over_ (vm, value);
+}
+
+void
+mix_vm_toggle_overflow (mix_vm_t *vm)
+{
+ g_return_if_fail (vm != NULL);
+ set_over_ (vm, !get_over_ (vm));
+}
+
+/* Access to memory cells */
+mix_word_t
+mix_vm_get_addr_contents (const mix_vm_t *vm, mix_address_t addr)
+{
+ g_return_val_if_fail (vm != NULL, MIX_WORD_ZERO);
+ g_return_val_if_fail (MEMOK_ (addr), MIX_WORD_ZERO);
+ return get_cell_ (vm, addr);
+}
+
+void
+mix_vm_set_addr_contents (mix_vm_t *vm, mix_address_t addr, mix_word_t value)
+{
+ g_return_if_fail (vm != NULL);
+ g_return_if_fail (MEMOK_ (addr));
+ set_cell_ (vm, addr, value);
+}
+
+gboolean
+mix_vm_is_halted (const mix_vm_t *vm)
+{
+ return is_halted_ (vm);
+}
+
+/* Execution of instructions */
+gboolean /* TRUE if success */
+mix_vm_exec_ins (mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_return_val_if_fail (vm != NULL, FALSE);
+ g_return_val_if_fail (ins != NULL, FALSE);
+ return (*ins_handlers_[ins->opcode]) (vm,ins);
+}
+
+/* comparison function for the line and address tables tree */
+static gint
+cmp_uint_ (gconstpointer a, gconstpointer b)
+{
+ return GPOINTER_TO_UINT (a) - GPOINTER_TO_UINT (b);
+}
+
+gboolean
+mix_vm_load_file (mix_vm_t *vm, const gchar *name)
+{
+ mix_code_file_t *file;
+ mix_ins_desc_t ins;
+ const gchar *sp;
+
+ g_return_val_if_fail (vm != NULL, FALSE);
+ file = mix_code_file_new_read (name);
+ if (file == NULL) return FALSE;
+ vm_reset_ (vm);
+ if ( mix_code_file_is_debug (file) )
+ {
+ vm->symbol_table = mix_code_file_get_symbol_table (file);
+ vm->line_table = g_tree_new (cmp_uint_);
+ vm->address_table = g_tree_new (cmp_uint_);
+ }
+
+ sp = mix_code_file_get_source_path (file);
+ if (sp != NULL)
+ vm->src_file = mix_src_file_new_for_read (sp);
+
+ while ( mix_code_file_get_ins (file, &ins) )
+ {
+ set_cell_ (vm, ins.address, ins.ins);
+ if ( vm->line_table != NULL )
+ {
+ g_tree_insert (vm->line_table,
+ GUINT_TO_POINTER (ins.lineno),
+ GUINT_TO_POINTER ((guint)ins.address));
+ g_tree_insert (vm->address_table,
+ GUINT_TO_POINTER ((guint)ins.address),
+ GUINT_TO_POINTER (ins.lineno));
+ }
+ }
+ set_loc_ (vm, mix_code_file_get_start_addr (file));
+ set_start_ (vm, get_loc_ (vm));
+ mix_code_file_delete (file);
+
+ return TRUE;
+}
+
+const mix_src_file_t *
+mix_vm_get_src_file (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, NULL);
+ return vm->src_file;
+}
+
+const mix_symbol_table_t *
+mix_vm_get_symbol_table (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, NULL);
+ return vm->symbol_table;
+}
+
+mix_address_t
+mix_vm_get_prog_count (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, MIX_SHORT_ZERO);
+ return get_loc_ (vm);
+}
+
+/* Get the source line number for a given address */
+guint
+mix_vm_get_address_lineno (const mix_vm_t *vm, mix_address_t addr)
+{
+ gpointer gp_addr = GUINT_TO_POINTER ((guint)addr);
+ guint lineno;
+
+ g_return_val_if_fail (vm != NULL, 0);
+ g_return_val_if_fail (MEMOK_ (addr), 0);
+ lineno = GPOINTER_TO_UINT (g_tree_lookup (vm->address_table, gp_addr));
+ return lineno;
+}
+
+/* Get the address for a given source line number */
+typedef struct
+{
+ guint lineno;
+ mix_address_t result;
+} addr_traverse_t;
+
+static gint
+get_address_ (gpointer key, gpointer value, gpointer data)
+{
+ addr_traverse_t *tr = (addr_traverse_t *)data;
+ if (GPOINTER_TO_UINT (key) == tr->lineno)
+ {
+ tr->result = mix_short_new (GPOINTER_TO_UINT (value));
+ return TRUE;
+ }
+ return (GPOINTER_TO_UINT (key) < tr->lineno)? FALSE:TRUE;
+}
+
+mix_address_t
+mix_vm_get_lineno_address (const mix_vm_t *vm, guint lineno)
+{
+ addr_traverse_t tr;
+
+ g_return_val_if_fail (vm != NULL, MIX_VM_CELL_NO);
+ if (!vm->line_table) return MIX_VM_CELL_NO;
+ tr.lineno = lineno;
+ tr.result = MIX_VM_CELL_NO;
+ g_tree_traverse (vm->line_table, get_address_, G_IN_ORDER, (gpointer)&tr);
+ return tr.result;
+}
+
+
+/* Reposition program counter and reset state so that a loaded
+ program can be restarted.
+*/
+void
+mix_vm_reset_program (mix_vm_t *vm)
+{
+ guint k;
+ g_return_if_fail (vm != NULL);
+ reset_loc_ (vm);
+ halt_ (vm, FALSE);
+ set_rA_ (vm, MIX_WORD_ZERO);
+ set_rX_ (vm, MIX_WORD_ZERO);
+ set_rJ_ (vm, MIX_WORD_ZERO);
+ for ( k = 1; k < IREG_NO_+1; ++k )
+ set_rI_ (vm, k, MIX_WORD_ZERO);
+ set_over_ (vm, FALSE);
+ set_cmp_ (vm, mix_EQ);
+}
+
+/* continue execution of instructions in memory */
+int
+mix_vm_run (mix_vm_t *vm)
+{
+ mix_ins_t ins;
+ g_return_val_if_fail (vm != NULL, MIX_VM_ERROR);
+
+ while ( !is_halted_ (vm) )
+ {
+ mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins);
+ if ( !(*ins_handlers_[ins.opcode]) (vm,&ins) )
+ return MIX_VM_ERROR;
+ else
+ update_time_ (vm, &ins);
+ if (bp_is_set_ (vm, get_loc_ (vm)))
+ return MIX_VM_BREAK;
+ if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE);
+ }
+ return MIX_VM_HALT;
+}
+
+/* execute next memory instruction */
+int
+mix_vm_exec_next (mix_vm_t *vm)
+{
+ mix_ins_t ins;
+ g_return_val_if_fail (vm != NULL, MIX_VM_ERROR);
+ if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE);
+ if (is_halted_ (vm)) return MIX_VM_HALT;
+ mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins);
+ if (!(*ins_handlers_[ins.opcode]) (vm, &ins))
+ return MIX_VM_ERROR;
+ else
+ update_time_ (vm, &ins);
+ if (is_halted_ (vm)) return MIX_VM_HALT;
+ return bp_is_set_ (vm, get_loc_ (vm)) ? MIX_VM_BREAK : MIX_VM_OK;
+}
+
+/* Breakpoints */
+gulong
+mix_vm_get_break_lineno (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, 0);
+ if (vm->address_table == NULL)
+ return 0;
+ else
+ {
+ gpointer loc = GUINT_TO_POINTER ((guint)get_loc_ (vm));
+ return GPOINTER_TO_UINT (g_tree_lookup (vm->address_table,loc));
+ }
+}
+
+typedef struct
+{
+ mix_vm_t *vm;
+ guint lineno;
+ gint result;
+} bp_traverse_t;
+
+static gint
+set_break_ (gpointer key, gpointer value, gpointer data)
+{
+ bp_traverse_t *tr = (bp_traverse_t *)data;
+ if (GPOINTER_TO_UINT (key) >= tr->lineno)
+ {
+ bp_set_ (tr->vm, mix_short_new (GPOINTER_TO_UINT (value)));
+ tr->lineno = GPOINTER_TO_UINT (key);
+ tr->result = MIX_VM_BP_OK;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gint /* if >0 the line no. of the break point */
+mix_vm_set_breakpoint (mix_vm_t *vm, guint lineno)
+{
+ bp_traverse_t tr;
+
+ g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR);
+ if (!vm->line_table) return MIX_VM_BP_NDEBUG;
+ tr.lineno = lineno;
+ tr.vm = vm;
+ tr.result = MIX_VM_BP_INV_LINE;
+ g_tree_traverse (vm->line_table, set_break_, G_IN_ORDER, (gpointer)&tr);
+ if (tr.result == MIX_VM_BP_OK)
+ return tr.lineno;
+ else
+ return tr.result;
+}
+
+gint
+mix_vm_set_breakpoint_address (mix_vm_t *vm, guint address)
+{
+ g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR);
+ if (address >= MIX_VM_CELL_NO)
+ return MIX_VM_BP_INV_ADDRESS;
+ else
+ bp_set_ (vm, mix_short_new (address));
+ return MIX_VM_BP_OK;
+}
+
+gboolean
+mix_vm_has_breakpoint_at_address (const mix_vm_t *vm, guint address)
+{
+ g_return_val_if_fail (vm != NULL, FALSE);
+ if (address >= MIX_VM_CELL_NO) return FALSE;
+ return (bp_is_set_ (vm, address));
+}
+
+static gint
+clear_break_ (gpointer key, gpointer value, gpointer data)
+{
+ bp_traverse_t *tr = (bp_traverse_t *)data;
+ if (GPOINTER_TO_UINT (key) == tr->lineno)
+ {
+ bp_clear_ (tr->vm, mix_short_new (GPOINTER_TO_UINT (value)));
+ tr->result = MIX_VM_BP_OK;
+ return TRUE;
+ }
+ else if (GPOINTER_TO_UINT (key) > tr->lineno)
+ return TRUE;
+
+ return FALSE;
+}
+
+gint /* one of MIX_VM_BP_ */
+mix_vm_clear_breakpoint (mix_vm_t *vm, guint lineno)
+{
+ bp_traverse_t tr;
+
+ g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR);
+ if (!vm->line_table) return MIX_VM_BP_NDEBUG;
+ tr.lineno = lineno;
+ tr.vm = vm;
+ tr.result = MIX_VM_BP_INV_LINE;
+ g_tree_traverse (vm->line_table, clear_break_, G_IN_ORDER, (gpointer)&tr);
+ return tr.result;
+}
+
+gint
+mix_vm_clear_breakpoint_address (mix_vm_t *vm, guint address)
+{
+ g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR);
+ if (address >= MIX_VM_CELL_NO)
+ return MIX_VM_BP_INV_ADDRESS;
+ else
+ bp_clear_ (vm, mix_short_new (address));
+ return MIX_VM_BP_OK;
+}
+
+void
+mix_vm_clear_all_breakpoints (mix_vm_t *vm)
+{
+ g_return_if_fail (vm != NULL);
+ bp_clear_all_ (vm);
+}
+
+/* Get the vm uptime, defined as the time spent executing instructions */
+mix_time_t
+mix_vm_get_uptime (const mix_vm_t *vm)
+{
+ g_return_val_if_fail (vm != NULL, 0);
+ return mix_vm_clock_get_time (get_clock_ (vm));
+}
+
diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h
new file mode 100644
index 0000000..b64e197
--- /dev/null
+++ b/mixlib/mix_vm.h
@@ -0,0 +1,204 @@
+/* ---------------------- mix_vm.h :
+ * Types and functions implementing the MIX virtual machine
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_VM_H
+#define MIX_VM_H
+
+#include "mix_types.h"
+#include "mix_ins.h"
+#include "mix_device.h"
+#include "mix_code_file.h"
+#include "mix_src_file.h"
+#include "mix_symbol_table.h"
+#include "mix_vm_clock.h"
+
+/* Comparison flag */
+typedef enum { mix_LESS, mix_EQ, mix_GREAT } mix_cmpflag_t;
+
+/* Number of memory cells in the virtual machine */
+enum { MIX_VM_CELL_NO = 4000 };
+
+/* Opaque type for the mix virtual machine */
+typedef struct mix_vm_t mix_vm_t;
+
+/* Create/destroy a mix vm */
+extern mix_vm_t *
+mix_vm_new(void);
+
+extern void
+mix_vm_delete(mix_vm_t * vm);
+
+/* connect devices to a virtual machine */
+extern mix_device_t * /* previously connected device */
+mix_vm_connect_device (mix_vm_t *vm, mix_device_t *device);
+
+/* Reset a vm (set state as of a newly created one) */
+extern void
+mix_vm_reset(mix_vm_t * vm);
+
+/* Set start address for execution */
+extern void
+mix_vm_set_start_addr(mix_vm_t *vm, mix_address_t addr);
+
+/* Access to the vm's registers */
+extern mix_word_t
+mix_vm_get_rA(const mix_vm_t *vm);
+
+extern mix_word_t
+mix_vm_get_rX(const mix_vm_t *vm);
+
+extern mix_short_t
+mix_vm_get_rJ(const mix_vm_t *vm);
+
+extern mix_short_t
+mix_vm_get_rI(const mix_vm_t *vm, guint idx);
+
+extern void
+mix_vm_set_rA(mix_vm_t *vm, mix_word_t value);
+
+extern void
+mix_vm_set_rX(mix_vm_t *vm, mix_word_t value);
+
+extern void
+mix_vm_set_rJ(mix_vm_t *vm, mix_short_t value);
+
+extern void
+mix_vm_set_rI(mix_vm_t *vm, guint idx, mix_short_t value);
+
+
+/* Access to the comparison flag and overflow toggle */
+extern mix_cmpflag_t
+mix_vm_get_cmpflag(const mix_vm_t *vm);
+
+extern void
+mix_vm_set_cmpflag(mix_vm_t *vm, mix_cmpflag_t value);
+
+extern gboolean
+mix_vm_get_overflow(const mix_vm_t *vm);
+
+extern void
+mix_vm_set_overflow(mix_vm_t *vm, gboolean value);
+
+extern void
+mix_vm_toggle_overflow(mix_vm_t *vm);
+
+extern gboolean
+mix_vm_is_halted(const mix_vm_t *vm);
+
+/* Access to memory cells */
+extern mix_word_t
+mix_vm_get_addr_contents(const mix_vm_t *vm, mix_address_t addr);
+
+extern void
+mix_vm_set_addr_contents(mix_vm_t *vm, mix_address_t addr, mix_word_t value);
+
+/* Execution of instructions and programs */
+extern gboolean /* TRUE if success */
+mix_vm_exec_ins(mix_vm_t *vm, const mix_ins_t *ins);
+
+/* Load a code file into memory (-name- does not need the default extension)
+ * resetting the vm's state
+ */
+extern gboolean
+mix_vm_load_file(mix_vm_t *vm, const gchar *name);
+
+/* Get the source file object corresponding to the last loaded code file */
+extern const mix_src_file_t *
+mix_vm_get_src_file (const mix_vm_t *vm);
+
+/* Get symbol table of loaded file */
+extern const mix_symbol_table_t *
+mix_vm_get_symbol_table (const mix_vm_t *vm);
+
+/* Get current program counter */
+extern mix_address_t
+mix_vm_get_prog_count (const mix_vm_t *vm);
+
+/* Get the source line number for a given address */
+extern guint
+mix_vm_get_address_lineno (const mix_vm_t *vm, mix_address_t addr);
+
+/* Get the address for a given source line number */
+extern mix_address_t
+mix_vm_get_lineno_address (const mix_vm_t *vm, guint lineno);
+
+/* Reposition program counter and reset state so that a loaded
+ program can be restarted.
+*/
+extern void
+mix_vm_reset_program (mix_vm_t *vm);
+
+/* continue execution of instructions in memory */
+/* Possible outcomes */
+enum {
+ MIX_VM_ERROR, /* error executing instructions */
+ MIX_VM_BREAK, /* breakpoint found */
+ MIX_VM_HALT, /* end of execution */
+ MIX_VM_OK /* successful instruction execution */
+};
+
+extern int
+mix_vm_run (mix_vm_t *vm);
+
+/* execute next memory instruction */
+extern int
+mix_vm_exec_next (mix_vm_t *vm);
+
+/* get the line no. of the last break or 0 if not found */
+extern gulong
+mix_vm_get_break_lineno (const mix_vm_t *vm);
+
+/* Breakpoints */
+/* possible error outcomes */
+enum {
+ MIX_VM_BP_ERROR = -4, /* internal error */
+ MIX_VM_BP_NDEBUG = -3, /* no debug info */
+ MIX_VM_BP_INV_ADDRESS = -2, /* address out of range */
+ MIX_VM_BP_INV_LINE = -1, /* invalid line no. */
+ MIX_VM_BP_OK = 0 /* success */
+};
+
+extern gint /* if >0 the line no. of the break point */
+mix_vm_set_breakpoint (mix_vm_t *vm, guint lineno);
+
+extern gint /* one of MIX_VM_BP_ */
+mix_vm_set_breakpoint_address (mix_vm_t *vm, guint address);
+
+extern gint /* one of MIX_VM_BP_ */
+mix_vm_clear_breakpoint (mix_vm_t *vm, guint lineno);
+
+extern gint /* one of MIX_VM_BP_ */
+mix_vm_clear_breakpoint_address (mix_vm_t *vm, guint address) ;
+
+extern gboolean
+mix_vm_has_breakpoint_at_address (const mix_vm_t *vm, guint address);
+
+extern void
+mix_vm_clear_all_breakpoints (mix_vm_t *vm);
+
+/* Get the vm uptime, defined as the time spent executing instructions */
+extern mix_time_t
+mix_vm_get_uptime (const mix_vm_t *vm);
+
+
+#endif /* MIX_VM_H */
+
diff --git a/mixlib/mix_vm_clock.c b/mixlib/mix_vm_clock.c
new file mode 100644
index 0000000..41e7116
--- /dev/null
+++ b/mixlib/mix_vm_clock.c
@@ -0,0 +1,68 @@
+/* -*-c-*- -------------- mix_vm_clock.c :
+ * Implementation of the functions declared in mix_vm_clock.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/02/20 00:23:58 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "mix_vm_clock.h"
+
+static const mix_time_t exec_times_[] = {
+ 1, 2, 2, 10, 12, 10, 2, 1,
+ 2, 2, 2, 2 , 2, 2, 2, 2,
+ 2, 2, 2, 2 , 2, 2, 2, 2,
+ 2, 2, 2, 2 , 2, 2, 2, 2,
+ 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2 , 2, 2, 2, 2
+};
+
+
+/* Create/delete a clock */
+mix_vm_clock_t *
+mix_vm_clock_new ()
+{
+ mix_vm_clock_t *result = g_new (mix_vm_clock_t, 1);
+ result->time = 0;
+ return result;
+}
+
+void
+mix_vm_clock_delete (mix_vm_clock_t *clock)
+{
+ g_return_if_fail (clock != NULL);
+}
+
+/* Increase time with the units needed to execute ins */
+mix_time_t
+mix_vm_clock_add_lapse (mix_vm_clock_t *clock, const mix_ins_t *ins)
+{
+ mix_time_t t = 0;
+ g_return_val_if_fail (clock != NULL, 0);
+ if (ins != NULL)
+ {
+ t = exec_times_[ins->opcode];
+ if (ins->opcode == mix_MOVE) t += 2 * (ins->fspec);
+ }
+ clock->time += t;
+ return t;
+}
+
diff --git a/mixlib/mix_vm_clock.h b/mixlib/mix_vm_clock.h
new file mode 100644
index 0000000..706115e
--- /dev/null
+++ b/mixlib/mix_vm_clock.h
@@ -0,0 +1,55 @@
+/* -*-c-*- ---------------- mix_vm_clock.h :
+ * Declaration of mix_vm_clock_t, a clock for the MIX virtual machine.
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/02/20 00:23:58 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_VM_CLOCK_H
+#define MIX_VM_CLOCK_H
+
+#include "mix.h"
+#include "mix_ins.h"
+
+/* the type of time unit */
+typedef gulong mix_time_t;
+
+/* the clock type */
+typedef struct mix_vm_clock_t
+{
+ mix_time_t time;
+} mix_vm_clock_t;
+
+/* Create/delete a clock */
+extern mix_vm_clock_t *
+mix_vm_clock_new ();
+
+extern void
+mix_vm_clock_delete (mix_vm_clock_t *clock);
+
+/* Increase time with the units needed to execute ins */
+extern mix_time_t /* the added lapse */
+mix_vm_clock_add_lapse (mix_vm_clock_t *clock, const mix_ins_t *ins);
+
+/* Get the time since creation */
+#define mix_vm_clock_get_time(clock) (clock? clock->time:0)
+
+#endif /* MIX_VM_CLOCK_H */
+
diff --git a/mixlib/mix_vm_command.c b/mixlib/mix_vm_command.c
new file mode 100644
index 0000000..9cc0d52
--- /dev/null
+++ b/mixlib/mix_vm_command.c
@@ -0,0 +1,1167 @@
+/* -*-c-*- -------------- mix_vm_command.c :
+ * Implementation of the functions declared in mix_vm_command.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/15 15:57:52 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "mix_vm_command.h"
+#include "mix_vm.h"
+#include "mix_vm_dump.h"
+#include "mix_eval.h"
+
+/* hooks */
+typedef struct
+{
+ mix_vm_cmd_hook_t func;
+ gpointer data;
+} hook_;
+
+typedef struct
+{
+ mix_vm_cmd_global_hook_t func;
+ gpointer data;
+} global_hook_;
+
+struct mix_vm_cmd_dispatcher_t
+{
+ mix_vm_t *vm; /* the virtual machine */
+ gboolean result; /* last command's outcome */
+ gchar *program; /* the name of the last loaded program */
+ FILE *out; /* message output file */
+ FILE *err; /* error output file */
+ mix_dump_context_t *dump; /* dump context for output */
+ mix_eval_t *eval; /* evaluator for w-expressions */
+ gboolean trace; /* tracing flag */
+ gboolean printtime; /* printing times flag */
+ mix_time_t uptime; /* total running time */
+ mix_time_t laptime; /* last run time */
+ mix_time_t progtime; /* current program running time */
+ hook_ pre_hooks[MIX_CMD_INVALID]; /* Pre-command hooks */
+ hook_ post_hooks[MIX_CMD_INVALID]; /* Post-command hooks */
+ global_hook_ global_pre; /* global pre-command hook */
+ global_hook_ global_post; /* global post-command hook */
+};
+
+/* command handlers */
+typedef gboolean (*Function_)(mix_vm_cmd_dispatcher_t *, const gchar *);
+#define DEC_FUN(name) \
+ static int cmd_##name (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+
+DEC_FUN (help_);
+DEC_FUN (load_);
+DEC_FUN (run_);
+DEC_FUN (next_);
+DEC_FUN (pc_);
+DEC_FUN (psym_);
+DEC_FUN (preg_);
+DEC_FUN (pflags_);
+DEC_FUN (pall_);
+DEC_FUN (pmem_);
+DEC_FUN (sreg_);
+DEC_FUN (scmp_);
+DEC_FUN (sover_);
+DEC_FUN (smem_);
+DEC_FUN (ssym_);
+DEC_FUN (sbp_);
+DEC_FUN (sbpa_);
+DEC_FUN (cbp_);
+DEC_FUN (cbpa_);
+DEC_FUN (cabp_);
+DEC_FUN (weval_);
+DEC_FUN (w2d_);
+DEC_FUN (tron_);
+DEC_FUN (troff_);
+
+/* internal command info struct */
+typedef struct {
+ const char *name; /* User printable name of the function. */
+ Function_ func; /* Function to call to do the job. */
+ const char *doc; /* Documentation for this function. */
+ const char *usage; /* Usage */
+} command_;
+
+/* available commands (in the same order as the type enum) */
+
+command_ commands_[] = {
+ { "help", cmd_help_, N_("Display this text"), "help [COMMAND]"},
+ { "load", cmd_load_, N_("Load a MIX code file"), "load FILENAME"},
+ { "run", cmd_run_, N_("Run loaded or given MIX code file"),
+ "run [FILENAME]"},
+ { "next", cmd_next_, N_("Execute next instruction(s)"),
+ "next [NO_OF_INS]"},
+ { "pc", cmd_pc_, N_("Print program counter value"), "pc" },
+ { "psym", cmd_psym_, N_("Print symbol value"), "psym [SYMBOLNAME]"},
+ { "preg", cmd_preg_, N_("Print register value"),
+ "preg [A | X | J | I[1-6]]"},
+ { "pflags", cmd_pflags_, N_("Print comparison and overflow flags"),
+ "pflags"},
+ { "pall", cmd_pall_, N_("Print all registers and flags"), "pall"},
+ { "pmem", cmd_pmem_, N_("Print memory contents in address range"),
+ "pmem FROM[-TO]"},
+ { "sreg", cmd_sreg_, N_("Set register value"),
+ "preg A | X | J | I[1-6] VALUE"},
+ { "scmp", cmd_scmp_, N_("Set comparison flag value"), "scmp L | E | G"},
+ { "sover", cmd_sover_, N_("Set overflow flag value"), "sover T | F" },
+ { "smem", cmd_smem_, N_("Set memory contents in given address"),
+ "smem ADDRESS VALUE"},
+ { "ssym", cmd_ssym_, N_("Set a symbol\'s value"), "ssym SYMBOL WEXPR"},
+ { "sbp", cmd_sbp_, N_("Set break point at given line"), "sbp LINENO"},
+ { "cbp", cmd_cbp_, N_("Clear break point at given line"), "cbp LINENO"},
+ { "sbpa", cmd_sbpa_, N_("Set break point at given address"),
+ "sbpa ADDRESS"},
+ { "cbpa", cmd_cbpa_, N_("Clear break point at given address"),
+ "cbpa ADDRESS"},
+ { "cabp", cmd_cabp_, N_("Clear all breakpoints"), "cabp"},
+ { "weval", cmd_weval_, N_("Evaluate a given W-expression"), "weval WEXPR"},
+ { "w2d", cmd_w2d_, N_("Convert a MIX word to its decimal value"),
+ "w2d WORD"},
+ { "tron", cmd_tron_, N_("Turn on instruction tracing."), "tron"},
+ { "troff", cmd_troff_, N_("Turn off instruction tracing."), "troff"},
+ { NULL, NULL, NULL, NULL},
+};
+
+
+/* external interface */
+
+/* conversion from/to commands to strings */
+const gchar *
+mix_vm_command_to_string (mix_vm_command_t cmd)
+{
+ if (cmd < MIX_CMD_INVALID) return commands_[cmd].name;
+ else return NULL;
+}
+
+mix_vm_command_t
+mix_vm_command_from_string (const gchar *name)
+{
+ /* inefficient linear search, i know */
+ gint cmd = 0;
+ while (cmd < MIX_CMD_INVALID && strcmp (name, commands_[cmd].name))
+ ++cmd;
+ return cmd;
+}
+
+/* get help string about a command */
+const gchar *
+mix_vm_command_help (mix_vm_command_t cmd)
+{
+ if (cmd < MIX_CMD_INVALID) return commands_[cmd].doc;
+ else return NULL;
+}
+
+const gchar *
+mix_vm_command_usage (mix_vm_command_t cmd)
+{
+ if (cmd < MIX_CMD_INVALID) return commands_[cmd].usage;
+ else return NULL;
+}
+
+/* create a new command dispatcher */
+mix_vm_cmd_dispatcher_t *
+mix_vm_cmd_dispatcher_new (FILE *out_fd, /* output messages file */
+ FILE *err_fd /* error messages file */)
+{
+ mix_vm_cmd_dispatcher_t *result = NULL;
+ int k;
+
+ g_return_val_if_fail (out_fd && err_fd, NULL);
+
+ result = g_new (mix_vm_cmd_dispatcher_t, 1);
+ result->result = TRUE;
+ result->out = out_fd;
+ result->err = err_fd;
+ result->uptime = result->laptime = result->progtime = 0;
+ result->printtime = TRUE;
+ result->trace = FALSE;
+ result->program = NULL;
+ result->eval = mix_eval_new ();
+ result->dump = mix_dump_context_new (out_fd,
+ MIX_SHORT_ZERO, MIX_SHORT_ZERO,
+ MIX_DUMP_ALL);
+ result->vm = mix_vm_new ();
+ result->global_pre.func = result->global_post.func = NULL;
+ result->global_pre.data = result->global_post.data = NULL;
+ for (k =0; k < MIX_CMD_INVALID; ++k)
+ {
+ result->pre_hooks[k].func = result->post_hooks[k].func = NULL;
+ result->pre_hooks[k].data = result->post_hooks[k].data = NULL;
+ }
+
+ return result;
+}
+
+/* delete (does not close the fds in the constructor) */
+extern void
+mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis)
+{
+ g_return_if_fail (dis != NULL);
+ mix_eval_delete (dis->eval);
+ mix_dump_context_delete (dis->dump);
+ mix_vm_delete (dis->vm);
+ g_free (dis);
+}
+
+/* install hooks */
+void
+mix_vm_cmd_dispatcher_pre_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd,
+ mix_vm_cmd_hook_t hook, gpointer data)
+{
+ g_return_if_fail (dis != NULL);
+ g_return_if_fail (cmd < MIX_CMD_INVALID);
+ dis->pre_hooks[cmd].func = hook;
+ dis->pre_hooks[cmd].data = data;
+}
+
+void
+mix_vm_cmd_dispatcher_post_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd,
+ mix_vm_cmd_hook_t hook, gpointer data)
+{
+ g_return_if_fail (dis != NULL);
+ g_return_if_fail (cmd < MIX_CMD_INVALID);
+ dis->post_hooks[cmd].func = hook;
+ dis->post_hooks[cmd].data = data;
+}
+
+void
+mix_vm_cmd_dispatcher_global_pre_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_cmd_global_hook_t hook,
+ gpointer data)
+{
+ g_return_if_fail (dis != NULL);
+ dis->global_pre.func = hook;
+ dis->global_pre.data = data;
+}
+
+void
+mix_vm_cmd_dispatcher_global_post_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_cmd_global_hook_t hook,
+ gpointer data)
+{
+ g_return_if_fail (dis != NULL);
+ dis->global_post.func = hook;
+ dis->global_post.data = data;
+}
+
+/* dispatch a command */
+gboolean /* TRUE if success, FALSE otherwise */
+mix_vm_cmd_dispatcher_dispatch (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd, const gchar *arg)
+{
+ g_return_val_if_fail (dis != NULL, FALSE);
+
+ if (dis->global_pre.func)
+ (dis->global_pre.func)(dis, cmd, arg, dis->global_pre.data);
+
+ if (cmd < MIX_CMD_INVALID)
+ {
+ if (dis->pre_hooks[cmd].func)
+ (dis->pre_hooks[cmd].func)(dis, arg, dis->pre_hooks[cmd].data);
+ dis->result = (commands_[cmd].func)(dis, arg);
+ if (dis->post_hooks[cmd].func)
+ (dis->post_hooks[cmd].func)(dis, arg, dis->post_hooks[cmd].data);
+ }
+ else
+ {
+ fprintf (dis->err, "Unknown command. Try: help");
+ }
+
+ if (dis->global_post.func)
+ (dis->global_post.func)(dis, cmd, arg, dis->global_post.data);
+
+ fflush (dis->out);
+ fflush (dis->err);
+ return dis->result;
+}
+
+/* dispatch a command in text format */
+gboolean
+mix_vm_cmd_dispatcher_dispatch_text (mix_vm_cmd_dispatcher_t *dis,
+ const gchar *text)
+{
+ gchar *cp, *arg = "";
+ int k = 0;
+ gboolean result;
+
+ g_return_val_if_fail (dis != NULL, FALSE);
+ g_return_val_if_fail (text != NULL, FALSE);
+
+ cp = g_strdup (text);
+ while (cp[k] && !isspace (cp[k])) ++k;
+ if (cp[k])
+ {
+ cp[k] = '\0'; ++k;
+ while (cp[k] && isspace (cp[k])) ++k;
+ arg = cp + k;
+ }
+
+ result = mix_vm_cmd_dispatcher_dispatch (dis,
+ mix_vm_command_from_string (cp),
+ arg);
+ g_free (cp);
+ return result;
+}
+
+/* get the last dispatch's result */
+gboolean
+mix_vm_cmd_dispatcher_get_last_result (const mix_vm_cmd_dispatcher_t *dis)
+{
+ g_return_val_if_fail (dis != NULL, FALSE);
+ return dis->result;
+}
+
+/* get total uptime */
+mix_time_t
+mix_vm_cmd_dispatcher_get_uptime (const mix_vm_cmd_dispatcher_t *dis)
+{
+ g_return_val_if_fail (dis != NULL, 0);
+ return dis->uptime;
+}
+
+/* get program total time */
+mix_time_t
+mix_vm_cmd_dispatcher_get_progtime (const mix_vm_cmd_dispatcher_t *dis)
+{
+ g_return_val_if_fail (dis != NULL, 0);
+ return dis->progtime;
+}
+
+/* get time lapse */
+mix_time_t
+mix_vm_cmd_dispatcher_get_laptime (const mix_vm_cmd_dispatcher_t *dis)
+{
+ g_return_val_if_fail (dis != NULL, 0);
+ return dis->laptime;
+}
+
+/* toggle time printing */
+void
+mix_vm_cmd_dispatcher_print_time (mix_vm_cmd_dispatcher_t * dis, gboolean print)
+{
+ g_return_if_fail (dis != NULL);
+ dis->printtime = print;
+}
+
+/* get the mix vm */
+const mix_vm_t *
+mix_vm_cmd_dispatcher_get_vm (const mix_vm_cmd_dispatcher_t *dis)
+{
+ g_return_val_if_fail (dis != NULL, NULL);
+ return dis->vm;
+}
+
+
+/* trace current instruction */
+static void
+trace_ (mix_vm_cmd_dispatcher_t *dis)
+{
+ enum {BUFFER_LEN = 128};
+ static gchar STRINS[BUFFER_LEN];
+
+ const mix_src_file_t *file = mix_vm_get_src_file (dis->vm);
+ const gchar *line = "\n";
+ mix_address_t loc = mix_vm_get_prog_count (dis->vm);
+ mix_word_t ins = mix_vm_get_addr_contents (dis->vm, loc);
+ mix_ins_t fins;
+ mix_word_to_ins_uncheck (ins, fins);
+ mix_ins_to_string_in_buffer (&fins, STRINS, BUFFER_LEN);
+
+ if (file != NULL)
+ {
+ gulong b = mix_vm_get_break_lineno (dis->vm);
+ if (b > 0) line = mix_src_file_get_line (file, b);
+ }
+
+ fprintf (dis->out, "%d: [%-15s]\t%s", (gint)loc, STRINS, line);
+}
+
+/* run a program tracing executed instructions */
+static int
+run_and_trace_ (mix_vm_cmd_dispatcher_t *dis)
+{
+ int k = MIX_VM_OK;
+ if (!dis->trace)
+ return mix_vm_run (dis->vm);
+ else while (k == MIX_VM_OK)
+ {
+ trace_ (dis);
+ k = mix_vm_exec_next (dis->vm);
+ }
+ return k;
+}
+
+/* print time statistics */
+static void
+print_time_ (mix_vm_cmd_dispatcher_t *dis)
+{
+ dis->laptime = mix_vm_get_uptime(dis->vm) - dis->uptime;
+ dis->uptime += dis->laptime;
+ dis->progtime += dis->laptime;
+ if (dis->printtime)
+ fprintf( dis->out,
+ _("Elapsed time: %ld /Total program time: %ld (Total uptime: %ld)\n"),
+ dis->laptime, dis->progtime, dis->uptime);
+}
+
+
+/* commands */
+
+static gboolean
+cmd_help_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ static const int NO_OF_COLS = 6;
+
+ int i;
+ int printed = 0;
+
+ for (i = 0; commands_[i].name; i++)
+ {
+ if (!*arg || (strcmp (arg, commands_[i].name) == 0))
+ {
+ fprintf (dis->out ,_("%s\t\t%s. Usage: %s\n"), commands_[i].name,
+ _(commands_[i].doc), commands_[i].usage);
+ printed++;
+ }
+ }
+
+ if (!printed)
+ {
+ fprintf (dis->out,
+ _("No commands match `%s'. Possibilities are:\n"), arg);
+
+ for (i = 0; commands_[i].name; i++)
+ {
+ if (printed == NO_OF_COLS)
+ {
+ printed = 0;
+ fprintf (dis->out, "\n");
+ }
+
+ fprintf (dis->out, "%s\t", commands_[i].name);
+ printed++;
+ }
+
+ if (printed)
+ fprintf (dis->out, "\n");
+ }
+ return TRUE;
+}
+
+static gboolean
+cmd_load_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ errno = 0;
+ if (arg == NULL || *arg == '\0')
+ {
+ fputs (_("Missing file name\n"), dis->err);
+ return FALSE;
+ }
+ mix_eval_remove_symbols_from_table (dis->eval,
+ mix_vm_get_symbol_table (dis->vm));
+ if (!mix_vm_load_file (dis->vm, arg) )
+ {
+ fprintf (dis->err, _("Cannot load %s: "), arg);
+ if ( errno == 0 )
+ fputs (_("Wrong file format\n"), dis->err);
+ else
+ fprintf (dis->err, "%s\n", strerror (errno));
+ return FALSE;
+ }
+
+ if (dis->program != arg)
+ {
+ if (dis->program) g_free (dis->program);
+ dis->program = g_strdup (arg);
+ }
+
+ mix_eval_set_symbols_from_table (dis->eval,
+ mix_vm_get_symbol_table (dis->vm));
+
+ fprintf (dis->out, _("Program loaded. Start address: %d\n"),
+ mix_vm_get_prog_count (dis->vm));
+
+ dis->laptime = dis->progtime = 0;
+ return TRUE;
+}
+
+
+static gboolean
+cmd_run_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ if (arg != NULL && *arg != '\0' && cmd_load_ (dis, arg) != TRUE)
+ return FALSE;
+
+ if (mix_vm_is_halted (dis->vm)) cmd_load_ (dis, dis->program);
+
+ fputs (_("Running ...\n"), dis->out);
+
+ switch (run_and_trace_ (dis))
+ {
+ case MIX_VM_HALT:
+ fputs (_("... done\n"), dis->out);
+ break;
+ case MIX_VM_BREAK:
+ {
+ gulong line = mix_vm_get_break_lineno (dis->vm);
+ if (line != 0)
+ fprintf (dis->out,
+ _("... stopped: breakpoint at line %ld (address %d)\n"),
+ line, mix_vm_get_prog_count (dis->vm));
+ else
+ fprintf (dis->out, _("... stopped: breakpoint at address %d\n"),
+ mix_vm_get_prog_count (dis->vm));
+ }
+ break;
+ case MIX_VM_ERROR:
+ fputs (_("... error executing loaded file"), dis->err);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ print_time_ (dis);
+
+ return TRUE;
+}
+
+static gboolean
+cmd_next_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ int ins_no = 1;
+ int k;
+
+ if ( strlen (arg) != 0 )
+ {
+ int k = 0;
+ while (isdigit (arg[k]))
+ k++;
+ if (arg[k] != '\0')
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "next");
+ return FALSE;
+ }
+ ins_no = atoi (arg);
+ }
+
+ if (mix_vm_is_halted (dis->vm)) cmd_load_ (dis, dis->program);
+
+ while ( ins_no-- > 0 )
+ {
+ if (dis->trace) trace_ (dis);
+ k = mix_vm_exec_next (dis->vm);
+ if (k == MIX_VM_HALT)
+ {
+ fprintf (dis->err, _("End of program reached at address %d\n"),
+ mix_vm_get_prog_count (dis->vm));
+ break;
+ }
+ else if (k == MIX_VM_ERROR)
+ {
+ fprintf (dis->err, _("Error at address %d\n"),
+ mix_vm_get_prog_count (dis->vm));
+ break;
+ }
+ }
+ print_time_ (dis);
+
+ return TRUE;
+}
+
+static gboolean
+cmd_pc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ fprintf (dis->out, "Current address: %d\n", mix_vm_get_prog_count (dis->vm));
+ return TRUE;
+}
+
+static gboolean
+cmd_psym_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ gboolean result = FALSE;
+ const mix_symbol_table_t *table = mix_eval_symbol_table (dis->eval);
+ if ( table == NULL )
+ fputs (_("Symbol table not available\n"), dis->err);
+ else if (arg != NULL && *arg != '\0')
+ {
+ if ( mix_symbol_table_is_defined (table, arg) )
+ {
+ mix_word_print (mix_symbol_table_value (table, arg), NULL);
+ putc ('\n', dis->out);
+ result = TRUE;
+ }
+ else
+ fprintf (dis->out, _("%s: symbol not defined\n"), arg);
+ }
+ else
+ {
+ mix_symbol_table_print (table, MIX_SYM_ROWS, stdout, TRUE);
+ result = TRUE;
+ }
+
+ return result;
+}
+
+static gboolean
+cmd_preg_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ mix_dump_context_set_opt (dis->dump, MIX_DUMP_NONE);
+ if ( strlen (arg) == 0 )
+ mix_dump_context_add_opt (dis->dump, MIX_DUMP_rALL);
+ else switch (*arg)
+ {
+ case 'A':
+ mix_dump_context_add_opt (dis->dump, MIX_DUMP_rA);
+ break;
+ case 'X':
+ mix_dump_context_add_opt (dis->dump, MIX_DUMP_rX);
+ break;
+ case 'J':
+ mix_dump_context_add_opt (dis->dump, MIX_DUMP_rJ);
+ break;
+ case 'I':
+ {
+ if ( strlen (arg) == 1 )
+ mix_dump_context_add_opt (dis->dump, MIX_DUMP_rIa);
+ else
+ {
+ static gint32 opt[] = { MIX_DUMP_rI1, MIX_DUMP_rI2,
+ MIX_DUMP_rI3, MIX_DUMP_rI4,
+ MIX_DUMP_rI5, MIX_DUMP_rI6
+ };
+ int i = arg[1] - '1';
+ if ( i < 0 || i > 5 )
+ {
+ fprintf (dis->err, _("Invalid I index: %d"), i);
+ return FALSE;
+ }
+ mix_dump_context_add_opt (dis->dump, opt[i]);
+ }
+ }
+ break;
+ default:
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ return FALSE;
+ }
+ mix_vm_dump (dis->vm, dis->dump);
+ return TRUE;
+}
+
+static gboolean
+cmd_pflags_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ mix_dump_context_set_opt (dis->dump, MIX_DUMP_CMP | MIX_DUMP_OVER);
+ mix_vm_dump (dis->vm, dis->dump);
+ return TRUE;
+}
+
+static gboolean
+cmd_pall_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ mix_dump_context_set_opt (dis->dump, MIX_DUMP_ALL_NOMEM);
+ mix_vm_dump (dis->vm, dis->dump);
+ return TRUE;
+}
+
+static gboolean
+cmd_pmem_ (mix_vm_cmd_dispatcher_t *dis, const gchar *carg)
+{
+ glong begin = MIX_SHORT_ZERO, end = MIX_SHORT_ZERO;
+ int i = 0;
+ gboolean error = FALSE;
+ gchar *arg = NULL;
+
+ if ( strlen (carg) == 0 )
+ {
+ fputs (_("Missing memory address\n"), dis->err);
+ return FALSE;
+ }
+ arg = g_strdup (carg);
+ while (isdigit (arg[i]))
+ i++;
+ while (isspace (arg[i]))
+ i++;
+ if (arg[i] == '\0')
+ begin = end = atol (arg);
+ else if (arg[i] == '-')
+ {
+ arg[i++] = '\0';
+ begin = atol (arg);
+ arg = arg + i;
+ i = 0;
+ while (isdigit (arg[i]))
+ i++;
+ while (isspace (arg[i]))
+ i++;
+ if (arg[i] != '\0')
+ error = TRUE;
+ else
+ end = atol (arg);
+ }
+ else
+ error = TRUE;
+
+ if (error)
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "pmem");
+ }
+ else if ( end < begin || end > MIX_VM_CELL_NO - 1 )
+ {
+ fprintf (dis->err, _("Invalid range: %ld-%ld\n"), begin, end);
+ error = TRUE;
+ }
+ else
+ {
+ mix_dump_context_set_opt (dis->dump, MIX_DUMP_CELLS);
+ mix_dump_context_range (dis->dump, mix_short_new (begin),
+ mix_short_new (end + 1));
+ mix_vm_dump (dis->vm, dis->dump);
+ }
+ g_free (arg);
+ return !error;
+}
+
+static gboolean
+cmd_sreg_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ int i = 0;
+ char reg = arg[0];
+ gboolean ok = TRUE;
+ long value;
+
+ i = (reg == 'I') ? 2 : 1;
+ ok = strlen (arg) > 2 && isspace (arg[i]);
+ if (ok)
+ {
+ while (isspace (arg[i])) i++;
+ ok = isdigit (arg[i]) || arg[i] == '+' || arg[i] == '-';
+ if (ok)
+ {
+ value = atol (arg + i);
+ if (arg[i] == '+' || arg[i] == '-') i++;
+ while (isdigit (arg[i])) i++;
+ ok = (arg[i] == '\0');
+ if (ok)
+ switch (reg)
+ {
+ case 'A':
+ mix_vm_set_rA (dis->vm, mix_word_new (value));
+ break;
+ case 'X':
+ mix_vm_set_rX (dis->vm, mix_word_new (value));
+ break;
+ case 'J':
+ if ( value >= 0 )
+ mix_vm_set_rJ (dis->vm, mix_short_new (value));
+ else
+ ok = FALSE;
+ break;
+ case 'I':
+ {
+ guint k = arg[1] - '0';
+ if ( k < 7 )
+ mix_vm_set_rI (dis->vm, k, mix_short_new (value));
+ else
+ ok = FALSE;
+ }
+ break;
+ default:
+ ok = FALSE;
+ }
+ }
+ }
+ if (!ok)
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "sreg");
+ }
+
+ return ok;
+}
+
+static gboolean
+cmd_scmp_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ gboolean ok = (strlen (arg) == 1);
+ if (ok) switch (arg[0])
+ {
+ case 'L':
+ mix_vm_set_cmpflag (dis->vm, mix_LESS);
+ break;
+ case 'E':
+ mix_vm_set_cmpflag (dis->vm, mix_EQ);
+ break;
+ case 'G':
+ mix_vm_set_cmpflag (dis->vm, mix_GREAT);
+ break;
+ default:
+ ok = FALSE;
+ }
+ if (!ok)
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "scmp");
+ }
+
+ return ok;
+}
+
+static gboolean
+cmd_sover_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ gboolean ok = (strlen (arg) == 1);
+ if (ok) switch (arg[0])
+ {
+ case 'T':
+ mix_vm_set_overflow (dis->vm, TRUE);
+ break;
+ case 'F':
+ mix_vm_set_overflow (dis->vm, FALSE);
+ break;
+ default:
+ ok = FALSE;
+ }
+ if (!ok)
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "sover");
+ }
+
+ return ok;
+}
+
+static gboolean
+cmd_smem_ (mix_vm_cmd_dispatcher_t *dis, const gchar *carg)
+{
+ gboolean ok = (strlen (carg) > 2 && isdigit (carg[0]));
+ gulong addr;
+ glong value;
+ int k = 0;
+ gchar *arg = NULL;
+
+ if (ok)
+ {
+ arg = g_strdup (carg);
+ while (isdigit (arg[k])) k++;
+ ok = isspace (arg[k]);
+ if (ok)
+ {
+ arg[k++] = '\0';
+ addr = atol (arg);
+ ok = addr < MIX_VM_CELL_NO;
+ }
+ if (ok)
+ {
+ while (isspace (arg[k])) k++;
+ value = atol (arg + k);
+ if ( arg[k] == '+' || arg[k] == '-' ) k++;
+ while (isdigit (arg[k])) k++;
+ ok = arg[k] == '\0';
+ }
+ }
+
+ if (ok)
+ mix_vm_set_addr_contents (dis->vm, mix_short_new (addr),
+ mix_word_new (value));
+ else
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "smem");
+ }
+ g_free (arg);
+
+ return ok;
+}
+
+static gboolean
+cmd_ssym_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ gboolean result = FALSE;
+ if (arg == NULL || strlen(arg) == 0)
+ {
+ fprintf (dis->err, _("Missing arguments\n"));
+ cmd_help_ (dis, "ssym");
+ }
+ else
+ {
+ gchar *a = g_strdup (arg);
+ gchar *s = strtok (a, " \t");
+ gchar *w = strtok (NULL, " \t");
+ if (w != NULL && strtok (NULL, " \t") == NULL)
+ {
+ cmd_weval_ (dis, w);
+ if (mix_eval_last_error (dis->eval) == MIX_EVAL_OK) {
+ mix_eval_set_symbol (dis->eval, s, mix_eval_value (dis->eval));
+ result = TRUE;
+ }
+ }
+ else
+ {
+ fprintf (dis->err, _("Wrong argument number\n"));
+ cmd_help_ (dis, "ssym");
+ }
+ g_free (a);
+ }
+ return result;
+}
+
+static gboolean
+cmd_sbp_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ glong lineno;
+ glong k = 0;
+ while (isdigit (arg[k])) k++;
+ if (arg[k] != '\0')
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "sbp");
+ return FALSE;
+ }
+ lineno = atol (arg);
+ switch (k = mix_vm_set_breakpoint (dis->vm, lineno))
+ {
+ case MIX_VM_BP_INV_LINE:
+ fprintf (dis->err, _("Line number %ld too high\n"), lineno);
+ break;
+ case MIX_VM_BP_ERROR:
+ fputs (_("Could not set breakpoint. Internal error\n"), dis->err);
+ break;
+ case MIX_VM_BP_NDEBUG:
+ fputs (_("Could not set breakpoint. No debug info available\n"),
+ dis->err);
+ break;
+ default:
+ fprintf (dis->err, _("Breakpoint set at line %ld\n"), k);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+cmd_sbpa_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ glong address;
+ glong k = 0;
+ while (isdigit (arg[k])) k++;
+ if (arg[k] != '\0')
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "sbpa");
+ return FALSE;
+ }
+ address = atol (arg);
+ switch (mix_vm_set_breakpoint_address (dis->vm, address))
+ {
+ case MIX_VM_BP_INV_ADDRESS:
+ fprintf (dis->err, _("Invalid address %ld\n"), address);
+ break;
+ case MIX_VM_BP_ERROR:
+ fputs (_("Could not set breakpoint. Internal error\n"), dis->err);
+ break;
+ default:
+ fprintf (dis->err, _("Breakpoint set at address %ld\n"), address);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+cmd_cbp_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ glong lineno;
+ int k = 0;
+ while (isdigit (arg[k])) k++;
+ if (arg[k] != '\0')
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "cbp");
+ return FALSE;
+ }
+ lineno = atol (arg);
+ switch (mix_vm_clear_breakpoint (dis->vm, lineno))
+ {
+ case MIX_VM_BP_INV_LINE:
+ fprintf (dis->err, _("No breakpoint set at line %ld\n"), lineno);
+ break;
+ case MIX_VM_BP_ERROR:
+ fputs (_("Could not set breakpoint. Internal error\n"), dis->err);
+ break;
+ case MIX_VM_BP_NDEBUG:
+ fputs (_("No debug info available\n"), dis->err);
+ break;
+ case MIX_VM_BP_OK:
+ fprintf (dis->err, _("Breakpoint cleared at line %ld\n"), lineno);
+ return TRUE;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ return FALSE;
+}
+
+static gboolean
+cmd_cbpa_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ glong address;
+ glong k = 0;
+ while (isdigit (arg[k])) k++;
+ if (arg[k] != '\0')
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "cbpa");
+ return FALSE;
+ }
+ address = atol (arg);
+ switch (mix_vm_clear_breakpoint_address (dis->vm, address))
+ {
+ case MIX_VM_BP_INV_ADDRESS:
+ fprintf (dis->err, _("Invalid address %ld\n"), address);
+ break;
+ case MIX_VM_BP_ERROR:
+ fputs (_("Could not clear breakpoint. Internal error\n"), dis->err);
+ break;
+ default:
+ fprintf (dis->err, _("Breakpoint cleared at address %ld\n"), address);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static gboolean
+cmd_cabp_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ if (strlen (arg) != 0)
+ {
+ fprintf (dis->err, _("Invalid argument: %s\n"), arg);
+ cmd_help_ (dis, "cabp");
+ return FALSE;
+ }
+ mix_vm_clear_all_breakpoints (dis->vm);
+ return TRUE;
+}
+
+static gboolean
+cmd_weval_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ if ( strlen (arg) == 0 )
+ {
+ cmd_help_ (dis, "weval");
+ return FALSE;
+ }
+
+ if (mix_eval_expression_with_loc (dis->eval, arg,
+ mix_vm_get_prog_count (dis->vm)) ==
+ MIX_EVAL_OK)
+ {
+ mix_word_print_to_file (mix_eval_value (dis->eval), NULL, dis->out);
+ putc ('\n', dis->out);
+ return TRUE;
+ }
+ else
+ {
+ gint pos = mix_eval_last_error_pos (dis->eval);
+ gint k, len = strlen (arg);
+ g_assert(pos > -1 && pos <= len);
+ for (k = 0; k<pos; ++k) fputc (arg[k], dis->err);
+ fputc ('\n', dis->err);
+ for (k = 0; k<pos; ++k) fputc (' ', dis->err);
+ for (k = pos; k < len; ++k) fputc (arg[k], dis->err);
+ fprintf (dis->err, _("\nEvaluation error: %s\n"),
+ mix_eval_last_error_string (dis->eval));
+ return FALSE;
+ }
+}
+
+static gboolean
+cmd_w2d_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ if ( strlen (arg) == 0 )
+ {
+ cmd_help_ (dis, "w2d");
+ return FALSE;
+ }
+ else
+ {
+ gchar *cp = g_strdup (arg), *a = cp;
+ mix_byte_t bytes[5] = {0, 0, 0, 0, 0};
+ gchar *b;
+ guint k = 0;
+ gboolean is_n = (a[0] == '-'), success = TRUE;
+ if (a[0] == '+' || a[0] == '-') ++a;
+ b = strtok (a, " \t");
+ while (b != NULL && k < 5)
+ {
+ if (strlen (b) != 2 || !isdigit(b[0]) || !isdigit(b[1]))
+ {
+ fprintf (dis->err, _("Incorrect byte specification: %s\n"), b);
+ success = FALSE;
+ b = NULL;
+ }
+ else
+ {
+ bytes[k++] = mix_byte_new (atoi (b));
+ b = strtok (NULL, " \t");
+ }
+ }
+ if (success)
+ {
+ if (strtok (NULL, "\t") != NULL)
+ {
+ fprintf (dis->err,
+ _("The expression %s does not fit in a word\n"), arg);
+ success = FALSE;
+ }
+ else
+ {
+ mix_word_t w = mix_bytes_to_word (bytes, k);
+ fprintf (dis->out, "%s%ld\n", is_n? "-":"+",
+ mix_word_magnitude (w));
+ }
+ }
+ g_free (cp);
+
+ return success;
+ }
+}
+
+static gboolean
+cmd_tron_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ dis->trace = TRUE;
+ fprintf (dis->out, _("Instruction tracing has been turned ON.\n"));
+ return TRUE;
+}
+
+static gboolean
+cmd_troff_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg)
+{
+ dis->trace = FALSE;
+ fprintf (dis->out, _("Instruction tracing has been turned OFF.\n"));
+ return TRUE;
+}
diff --git a/mixlib/mix_vm_command.h b/mixlib/mix_vm_command.h
new file mode 100644
index 0000000..856c2d5
--- /dev/null
+++ b/mixlib/mix_vm_command.h
@@ -0,0 +1,160 @@
+/* -*-c-*- ---------------- mix_vm_command.h :
+ * declarations for mix_vm_command_t, describing commands issued to a vm
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/15 15:57:36 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIX_VM_COMMAND_H
+#define MIX_VM_COMMAND_H
+
+#include <stdio.h>
+#include "mix.h"
+#include "mix_vm.h"
+
+/* mix_vm_cmd_dispatcher encapsulates a virtual machine and helper
+ objects, providing a command driven interface with output to
+ provided files (in the posix sense).
+*/
+typedef struct mix_vm_cmd_dispatcher_t mix_vm_cmd_dispatcher_t;
+
+/* mix_vm_cmd_dispatcher understands the commands of this type */
+typedef enum {
+ MIX_CMD_HELP = 0, /* echo help message */
+ MIX_CMD_LOAD, /* load a mix program */
+ MIX_CMD_RUN, /* run a loaded program */
+ MIX_CMD_NEXT, /* run next instruction */
+ MIX_CMD_LOC, /* print location pointer */
+ MIX_CMD_PSYM, /* print symbol */
+ MIX_CMD_PREG, /* print registry */
+ MIX_CMD_PFLAGS, /* print comp and overf flags */
+ MIX_CMD_PALL, /* print all registers and flags */
+ MIX_CMD_PMEM, /* print memory cells */
+ MIX_CMD_SREG, /* set register value */
+ MIX_CMD_SCMP, /* set comparison flag value */
+ MIX_CMD_SOVER, /* set overflow toggle value */
+ MIX_CMD_SMEM, /* set memory cell value */
+ MIX_CMD_SSYM, /* set symbol value */
+ MIX_CMD_SBP, /* set breakpoint at lineno */
+ MIX_CMD_CBP, /* clear breakpoint at lineno */
+ MIX_CMD_SBPA, /* set breakpoint at address */
+ MIX_CMD_CBPA, /* clear breakpoint at address */
+ MIX_CMD_CABP, /* clear all breakpoints */
+ MIX_CMD_WEVAL, /* evaluate a w-expression */
+ MIX_CMD_W2D, /* print word in decimal notation */
+ MIX_CMD_TRON, /* enable instruction traces */
+ MIX_CMD_TROFF, /* disble instruction traces */
+ MIX_CMD_INVALID, /* invalid command identifier */
+} mix_vm_command_t;
+
+/* hook functions, to be invoked before and/or after command execution */
+typedef void (*mix_vm_cmd_hook_t)(mix_vm_cmd_dispatcher_t *dis,
+ const gchar *arg, gpointer data);
+
+/* global hook functions */
+typedef void (*mix_vm_cmd_global_hook_t)(mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd,
+ const gchar *arg, gpointer data);
+
+/* conversion from/to commands to strings */
+extern const gchar *
+mix_vm_command_to_string (mix_vm_command_t cmd);
+
+extern mix_vm_command_t
+mix_vm_command_from_string (const gchar *name);
+
+/* get help string about a command */
+extern const gchar *
+mix_vm_command_help (mix_vm_command_t cmd);
+
+extern const gchar *
+mix_vm_command_usage (mix_vm_command_t cmd);
+
+
+/* create a new command dispatcher */
+extern mix_vm_cmd_dispatcher_t *
+mix_vm_cmd_dispatcher_new (FILE *out_fd, /* output messages file */
+ FILE *err_fd /* error messages file */);
+
+/* delete (does not close the fds in the constructor) */
+extern void
+mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis);
+
+/* dispatch a command */
+extern gboolean /* TRUE if success, FALSE otherwise */
+mix_vm_cmd_dispatcher_dispatch (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd, const gchar *arg);
+
+/* dispatch a command in text format */
+extern gboolean
+mix_vm_cmd_dispatcher_dispatch_text (mix_vm_cmd_dispatcher_t *dis,
+ const gchar *text);
+
+/* get the last dispatch's result */
+extern gboolean
+mix_vm_cmd_dispatcher_get_last_result (const mix_vm_cmd_dispatcher_t *dis);
+
+/* get total uptime */
+extern mix_time_t
+mix_vm_cmd_dispatcher_get_uptime (const mix_vm_cmd_dispatcher_t *dis);
+
+/* get program total time */
+extern mix_time_t
+mix_vm_cmd_dispatcher_get_progtime (const mix_vm_cmd_dispatcher_t *dis);
+
+/* get time lapse */
+extern mix_time_t
+mix_vm_cmd_dispatcher_get_laptime (const mix_vm_cmd_dispatcher_t *dis);
+
+/* toggle time printing */
+extern void
+mix_vm_cmd_dispatcher_print_time (mix_vm_cmd_dispatcher_t * dis,
+ gboolean print);
+
+/* install hooks */
+extern void
+mix_vm_cmd_dispatcher_pre_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd,
+ mix_vm_cmd_hook_t hook, gpointer data);
+
+extern void
+mix_vm_cmd_dispatcher_post_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_command_t cmd,
+ mix_vm_cmd_hook_t hook, gpointer data);
+
+extern void
+mix_vm_cmd_dispatcher_global_pre_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_cmd_global_hook_t hook,
+ gpointer data);
+
+extern void
+mix_vm_cmd_dispatcher_global_post_hook (mix_vm_cmd_dispatcher_t *dis,
+ mix_vm_cmd_global_hook_t hook,
+ gpointer data);
+
+
+
+/* get the mix vm */
+extern const mix_vm_t *
+mix_vm_cmd_dispatcher_get_vm (const mix_vm_cmd_dispatcher_t *dis);
+
+
+#endif /* MIX_VM_COMMAND_H */
+
diff --git a/mixlib/mix_vm_dump.c b/mixlib/mix_vm_dump.c
new file mode 100644
index 0000000..91953fd
--- /dev/null
+++ b/mixlib/mix_vm_dump.c
@@ -0,0 +1,147 @@
+/* ---------------------- mix_vm_dump.c :
+ * Implementation of the functions declared in mix_vm_dump.h
+ * ------------------------------------------------------------------
+** Copyright (C) 2000 Free Software Foundation, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+#include "mix.h"
+#include <unistd.h>
+#include "xmix_vm.h"
+#include "mix_vm_dump.h"
+
+/* Create/destroy a dump context */
+mix_dump_context_t *
+mix_dump_context_new(FILE *fd, mix_address_t begin, mix_address_t end,
+ guint32 options)
+{
+ mix_dump_context_t *result = NULL;
+
+ g_return_val_if_fail (fd != NULL, NULL);
+
+ if ( begin > end ) begin = end;
+ if ( end >= MEM_CELLS_NO_ ) end = MEM_CELLS_NO_;
+
+ result = g_new (mix_dump_context_t,1);
+ result->options = options;
+ result->begin = begin;
+ result->end = end;
+ result->channel = fd;
+
+ return result;
+}
+
+void
+mix_dump_context_delete (mix_dump_context_t *dc)
+{
+ g_return_if_fail (dc != NULL);
+ g_free (dc);
+}
+
+/* Use the dump context */
+#define WORD_FMT_ "%s %02d %02d %02d %02d %02d (%010ld)"
+#define SHORT_FMT_ "%s %02d %02d (%04d)"
+#define WORD_SIGN_(w) mix_word_is_negative (w)? "-":"+"
+#define SHORT_SIGN_(s) mix_short_is_negative (s)? "-":"+"
+#define WORD_ABS_(w) mix_word_magnitude (w)
+#define SHORT_ABS_(s) mix_short_magnitude (s)
+#define WORD_BYTE_(w,i) mix_byte_new (mix_word_magnitude (w)>>(6*(5-i)))
+#define SHORT_BYTE_(s,i) mix_byte_new (mix_short_magnitude (s)>>(6*(2-i)))
+#define WORD_ARGS_(w) WORD_SIGN_ (w), WORD_BYTE_ (w,1), WORD_BYTE_ (w,2), \
+ WORD_BYTE_ (w,3), WORD_BYTE_ (w,4), WORD_BYTE_ (w,5), WORD_ABS_ (w)
+#define SHORT_ARGS_(s) SHORT_SIGN_ (s), SHORT_BYTE_ (s,1), SHORT_BYTE_ (s,2), \
+ SHORT_ABS_ (s)
+
+void
+mix_vm_dump (const mix_vm_t *vm, const mix_dump_context_t *dc)
+{
+ guint j, i;
+ FILE *f;
+
+ g_return_if_fail (vm != NULL);
+ g_return_if_fail (dc != NULL);
+
+ f = dc->channel;
+
+ if ( (dc->options & MIX_DUMP_rA) == MIX_DUMP_rA )
+ {
+ mix_word_t rA = get_rA_ (vm);
+ fprintf (f, "rA: " WORD_FMT_ "\n", WORD_ARGS_ (rA));
+ }
+
+ if ( (dc->options & MIX_DUMP_rX) == MIX_DUMP_rX )
+ {
+ mix_word_t rX = get_rX_ (vm);
+ fprintf (f, "rX: " WORD_FMT_ "\n", WORD_ARGS_ (rX));
+ }
+
+ if ( (dc->options & MIX_DUMP_rJ) == MIX_DUMP_rJ )
+ {
+ mix_short_t rJ = get_rJ_ (vm);
+ fprintf (f, "rJ: " SHORT_FMT_ "\n", SHORT_ARGS_ (rJ));
+ }
+
+ for (j = 0, i = 0; j < IREG_NO_; ++j)
+ {
+ if ( (dc->options & (MIX_DUMP_rI1<<j)) == (MIX_DUMP_rI1<<j) )
+ {
+ mix_short_t rI = mix_word_to_short_fast (get_rI_ (vm, j+1));
+ fprintf (f, "rI%d: " SHORT_FMT_ "\t", j+1, SHORT_ARGS_ (rI));
+ i++;
+ }
+ if ( i%2 == 0 && i != 0 ) fprintf (f, "\n");
+ }
+
+ if ( i%2 == 1 ) fprintf (f, "\n");
+
+ if ( (dc->options & MIX_DUMP_OVER) == MIX_DUMP_OVER )
+ {
+ fprintf (f, _("Overflow: %s\n"), get_over_ (vm)? "T":"F");
+ }
+
+ if ( (dc->options & MIX_DUMP_CMP) == MIX_DUMP_CMP )
+ {
+ const gchar *val = "?";
+ switch (get_cmp_ (vm))
+ {
+ case mix_LESS:
+ val = "L";
+ break;
+ case mix_GREAT:
+ val = "G";
+ break;
+ case mix_EQ:
+ val = "E";
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ fprintf (f, _("Cmp: %s\n"), val);
+ }
+
+ if ( (dc->options & MIX_DUMP_CELLS) == MIX_DUMP_CELLS )
+ {
+ for (j = dc->begin; j < dc->end; ++j)
+ {
+ mix_word_t cell = get_cell_ (vm,j);
+ fprintf (f, "%04d: " WORD_FMT_ "\n", j, WORD_ARGS_ (cell));
+ }
+ }
+ fflush (f);
+}
+
diff --git a/mixlib/mix_vm_dump.h b/mixlib/mix_vm_dump.h
new file mode 100644
index 0000000..8c5e1bd
--- /dev/null
+++ b/mixlib/mix_vm_dump.h
@@ -0,0 +1,91 @@
+/* ---------------------- mix_vm_dump.h :
+ * This file declares types and functions for dumping the contents
+ * of a mix virtual machine.
+ * ------------------------------------------------------------------
+** Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+
+#ifndef MIX_VM_DUMP_H
+#define MIX_VM_DUMP_H
+
+#include <stdio.h>
+#include "mix_vm.h"
+
+/* Dump context: a structure defining the properties of dumping */
+typedef struct mix_dump_context_t mix_dump_context_t;
+struct mix_dump_context_t
+{
+ /* flags activating dumps (see enum below) */
+ guint32 options;
+ /* range of addresses dumped: [begin,end) */
+ mix_address_t begin;
+ mix_address_t end;
+ /* IO channel for dumping */
+ FILE *channel;
+};
+
+/* Flags for activating dumps */
+#define MIX_DUMP_NONE 0
+#define MIX_DUMP_rA 1
+#define MIX_DUMP_rX (1<<1)
+#define MIX_DUMP_rJ (1<<2)
+#define MIX_DUMP_rI1 (1<<3)
+#define MIX_DUMP_rI2 (1<<4)
+#define MIX_DUMP_rI3 (1<<5)
+#define MIX_DUMP_rI4 (1<<6)
+#define MIX_DUMP_rI5 (1<<7)
+#define MIX_DUMP_rI6 (1<<8)
+#define MIX_DUMP_rIa MIX_DUMP_rI1|MIX_DUMP_rI2|MIX_DUMP_rI3 \
+ |MIX_DUMP_rI4|MIX_DUMP_rI5|MIX_DUMP_rI6
+#define MIX_DUMP_rALL MIX_DUMP_rA|MIX_DUMP_rX|MIX_DUMP_rJ|MIX_DUMP_rIa
+#define MIX_DUMP_OVER (1<<9)
+#define MIX_DUMP_CMP (1<<10)
+#define MIX_DUMP_CELLS (1<<11)
+#define MIX_DUMP_ALL MIX_DUMP_rALL|MIX_DUMP_OVER|MIX_DUMP_CMP|MIX_DUMP_CELLS
+#define MIX_DUMP_ALL_NOMEM MIX_DUMP_rALL|MIX_DUMP_OVER|MIX_DUMP_CMP
+
+/* Default output channel (stdout) */
+#define MIX_DUMP_DEF_CHANNEL (stdout)
+
+/* Create/destroy a dump context */
+extern mix_dump_context_t *
+mix_dump_context_new (FILE *fd, mix_address_t begin, mix_address_t end,
+ guint32 options);
+
+extern void
+mix_dump_context_delete(mix_dump_context_t *dc);
+
+/* Modify an existing dump context */
+#define mix_dump_context_add_opt(dc,opt) ((dc)->options |= (opt))
+#define mix_dump_context_del_opt(dc,opt) ((dc)->options &= ~(opt))
+#define mix_dump_context_set_opt(dc,opt) ((dc)->options = (opt))
+#define mix_dump_context_range(dc,first,last) \
+do { \
+ (dc)->begin = first; \
+ (dc)->end = last; \
+} while (FALSE)
+
+
+/* Use the dump context */
+extern void
+mix_vm_dump(const mix_vm_t *vm, const mix_dump_context_t *dc);
+
+
+#endif /* MIX_VM_DUMP_H */
+
diff --git a/mixlib/testsuite/.cvsignore b/mixlib/testsuite/.cvsignore
new file mode 100644
index 0000000..c936d6c
--- /dev/null
+++ b/mixlib/testsuite/.cvsignore
@@ -0,0 +1,28 @@
+.deps
+Makefile
+Makefile.in
+cardwr.dev
+disk0.dev
+disk1.dev
+disk2.dev
+disk3.dev
+disk4.dev
+disk5.dev
+disk6.dev
+disk7.dev
+mixdevtest
+mixevaltest
+mixinstest
+mixparsertest
+mixtypest
+mixvminstest
+paper.dev
+printer.dev
+tape0.dev
+tape1.dev
+tape2.dev
+tape3.dev
+tape4.dev
+tape5.dev
+tape6.dev
+tape7.dev
diff --git a/mixlib/testsuite/Makefile.am b/mixlib/testsuite/Makefile.am
new file mode 100644
index 0000000..6e771c4
--- /dev/null
+++ b/mixlib/testsuite/Makefile.am
@@ -0,0 +1,28 @@
+# Copyright (C) 1999 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+INCLUDES = -I..
+LDADD = $(top_builddir)/mixlib/libmix.a
+
+check_PROGRAMS = mixtypest mixinstest mixvminstest mixparsertest mixdevtest mixevaltest
+TESTS = $(check_PROGRAMS)
+
+mixtypest_SOURCES = test.h mix_types_t.c
+mixinstest_SOURCES = test.h mix_ins_t.c
+mixvminstest_SOURCES = test.h mix_vm_ins_t.c
+mixparsertest_SOURCES = test.h mix_parser_t.c
+mixdevtest_SOURCES = test.h mix_device_t.c
+mixevaltest_SOURCES = test.h mix_eval_t.c
+
+
+
+
+
+
diff --git a/mixlib/testsuite/mix_device_t.c b/mixlib/testsuite/mix_device_t.c
new file mode 100644
index 0000000..da4c8f9
--- /dev/null
+++ b/mixlib/testsuite/mix_device_t.c
@@ -0,0 +1,76 @@
+/* -*-c-*- -------------- mix_device_t.c :
+ * Implementation of the functions declared in mix_device_t.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <mix_device.h>
+
+/* Define VERBOSE_TEST if you want to get prints of the test */
+/* #define VERBOSE_TEST */
+#include "test.h"
+
+static int S_ = MIX_CHAR_MAX +1;
+
+int
+main (int argc, char **argv)
+{
+ mix_device_t *console;
+ size_t s;
+ mix_word_t **block;
+ mix_char_t mchars[S_];
+ gchar chars[S_];
+ int i, j;
+ int bno;
+
+
+ INIT_TEST;
+
+ console = mix_device_new (mix_dev_CONSOLE);
+ s = mix_device_block_size (console);
+ bno = S_/(s*5);
+ if (bno == 0) bno = 1;
+
+ block = g_new (mix_word_t *, bno);
+ for (i = 0; i < bno; ++i)
+ block[i] = g_new (mix_word_t, s);
+
+ for (i = 0; i < S_; ++i) {
+ chars[i] = mix_char_to_ascii (i);
+ mchars[i] = mix_ascii_to_char (chars[i]);
+ g_assert (mchars[i] == i);
+ }
+
+ for (i = 0; i < bno; ++i) {
+ for (j = 0; j < s; ++j) {
+ int n = i*s + 5*j;
+ if (n < S_)
+ block[i][j] = mix_bytes_to_word (mchars + n, 5);
+ else
+ block[i][j] = 0;
+ }
+ }
+
+ for (i = 0; i < bno; ++i) {
+ mix_device_write (console, block[i]);
+ }
+
+
+ return EXIT_SUCCESS;
+}
diff --git a/mixlib/testsuite/mix_eval_t.c b/mixlib/testsuite/mix_eval_t.c
new file mode 100644
index 0000000..83f9a5d
--- /dev/null
+++ b/mixlib/testsuite/mix_eval_t.c
@@ -0,0 +1,119 @@
+/* -*-c-*- -------------- mix_eval_t.c :
+ * Test of mix_eval_t
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/02/20 00:26:15 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include <stdlib.h>
+#include <mix_eval.h>
+/* Define VERBOSE_TEST if you want to get prints of the test */
+/* #define VERBOSE_TEST */
+#include "test.h"
+
+typedef struct test_case_t
+{
+ const gchar *expr;
+ gint value;
+ mix_eval_result_t result;
+} test_case_t;
+
+#define ok_case(exp,val) {exp, val, MIX_EVAL_OK}
+#define err_case(exp,err) {exp, 0, err}
+
+typedef struct sym_val_t
+{
+ const gchar *sym;
+ mix_word_t value;
+} sym_val_t;
+
+#define new_symbol(sym,val) {sym, mix_word_new (val)}
+
+int
+main(int argc, char **argv)
+{
+ size_t k;
+ mix_eval_t *eval;
+ mix_short_t loc = mix_short_new (30);
+ sym_val_t symbols[] = {
+ new_symbol ("s0", 43),
+ new_symbol ("s1", -1234),
+ new_symbol ("s2", 0),
+ new_symbol ("s3", -20),
+ new_symbol (NULL, 0)
+ };
+
+ test_case_t cases[] = {
+ ok_case ("2343", 2343),
+ ok_case ("-890", -890),
+ ok_case ("15+1015", 1030),
+ ok_case ("1-481", -480),
+ ok_case ("2300/10", 230),
+ ok_case ("24*3", 72),
+ ok_case ("2:5", 21),
+ ok_case ("1//3", 357913941),
+ ok_case ("12+*", 42),
+ ok_case ("***", 900),
+ ok_case ("1:3*2-4", 18),
+ ok_case ("-1+5*20/6", 13),
+ ok_case ("-1000(0,2),1", 1),
+ ok_case ("s0-s2*3", 129),
+ ok_case ("s3**", -600),
+ ok_case ("s3(3:5)", 20),
+ ok_case ("-s1", 1234),
+ ok_case ("s1/10+s0", 166),
+ err_case ("foo", MIX_EVAL_UNDEF_SYM),
+ err_case ("11--2", MIX_EVAL_SYNTAX),
+ err_case ("s2*foo*3", MIX_EVAL_UNDEF_SYM),
+ err_case ("12/32),1", MIX_EVAL_MIS_PAREN),
+ err_case ("2000(88)", MIX_EVAL_INV_FSPEC),
+ ok_case (NULL, 0)
+ };
+
+ INIT_TEST;
+ g_print ("Entering mix_eval test...");
+ eval = mix_eval_new ();
+
+ for (k = 0; symbols[k].sym; ++k)
+ mix_eval_set_symbol (eval, symbols[k].sym, symbols[k].value);
+
+ for (k = 0; cases[k].expr; ++k) {
+ mix_eval_result_t r = cases[k].result, s;
+ g_print ("Evaluating \"%s\" = %d ...",
+ cases[k].expr, cases[k].value);
+
+ s = mix_eval_expression_with_loc (eval, cases[k].expr, loc);
+ g_assert (s == r);
+ if ( s == MIX_EVAL_OK ) {
+ mix_word_print (mix_eval_value (eval), "... ");
+ g_print ("\n");
+ g_assert (mix_eval_value (eval) == mix_word_new(cases[k].value));
+ } else {
+ g_print ("\n------->%s, at pos %d\n",
+ mix_eval_last_error_string (eval),
+ mix_eval_last_error_pos (eval));
+ }
+ }
+ mix_eval_delete (eval);
+
+ return EXIT_SUCCESS;
+}
+
+
diff --git a/mixlib/testsuite/mix_ins_t.c b/mixlib/testsuite/mix_ins_t.c
new file mode 100644
index 0000000..f643b47
--- /dev/null
+++ b/mixlib/testsuite/mix_ins_t.c
@@ -0,0 +1,79 @@
+/*----------------------- mix_ins_t.c -------------------------------
+ * Tests for mix_ins.h
+ *-------------------------------------------------------------------
+** Copyright (C) 1999 Free Software Foundation, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+#include <stdlib.h>
+#include <mix_ins.h>
+
+/* Define VERBOSE_TEST if you want to get prints of the test */
+/* #define VERBOSE_TEST */
+#include "test.h"
+
+
+int
+main(int argc, const char**argv)
+{
+ mix_word_t words[6];
+ mix_ins_t ins[3];
+ guint k;
+
+ INIT_TEST;
+
+ g_print("\n...ok.\nTesting mix_ins_id_t properties...\n");
+ for ( k = 0; k < mix_INVALID_INS; ++k )
+ {
+ mix_opcode_t c = mix_get_opcode_from_id(k);
+ mix_fspec_t f = mix_get_fspec_from_id(k);
+ mix_ins_id_t id = mix_get_ins_id(c,f);
+
+ g_print("%02d:%s (%1d:%1d), ",
+ c, mix_get_string_from_id(k),
+ mix_fspec_left(f), mix_fspec_right(f));
+ if ( (k+1)%3 == 0 ) g_print("\n");
+
+ g_assert(id==k);
+ }
+
+ g_print("\n...ok.\nTesting mix_ins_t properties...\n");
+ for ( k = 1; k < mix_INVALID_INS; ++k )
+ {
+ g_print("%d ",k);
+ mix_ins_fill_from_id(ins[0], k);
+ g_assert(mix_ins_id_from_ins(ins[0]) == k);
+ ins[0].address = 0x0123;
+ ins[0].index = mix_I2;
+ words[2] = mix_ins_to_word(ins);
+ g_assert(ins[0].address == mix_get_ins_address(words[2]));
+ g_assert(ins[0].index == mix_get_ins_index(words[2]));
+ g_assert(ins[0].fspec == mix_get_ins_fspec(words[2]));
+ g_assert(ins[0].opcode == mix_get_ins_opcode(words[2]));
+ g_assert(mix_word_to_ins(words[2],ins+1) == k);
+ g_assert(ins[0].address == ins[1].address);
+ g_assert(ins[0].index == ins[1].index);
+ g_assert(ins[0].fspec == ins[1].fspec);
+ g_assert(ins[0].opcode == ins[1].opcode);
+ }
+
+ g_print("\n...ok.\n");
+
+
+
+ return EXIT_SUCCESS;
+}
diff --git a/mixlib/testsuite/mix_parser_t.c b/mixlib/testsuite/mix_parser_t.c
new file mode 100644
index 0000000..7bfa9d0
--- /dev/null
+++ b/mixlib/testsuite/mix_parser_t.c
@@ -0,0 +1,85 @@
+/* -*-c-*- -------------- mix_parser_t.c :
+ * Test of mix_parser_t
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+
+#include <stdlib.h>
+#include <mix_parser.h>
+
+/* Define VERBOSE_TEST if you want to get prints of the test */
+/* #define VERBOSE_TEST */
+#include "test.h"
+
+static const gchar * const FILES_[] = { "test1" , "taocp145"
+};
+
+static const size_t FILE_NO_ = sizeof(FILES_)/sizeof(FILES_[0]);
+
+static void
+test_code_(const gchar *name)
+{
+ mix_parser_t *parser = mix_parser_new(name);
+ mix_parser_err_t err;
+ mix_code_file_t *code;
+ mix_ins_desc_t ins;
+
+ g_assert(parser);
+ err = mix_parser_compile(parser);
+ if ( err != MIX_PERR_OK ) {
+ g_print(mix_parser_err_string(err));
+ g_print("\n");
+ }
+ g_assert(err == MIX_PERR_OK);
+ err = mix_parser_write_code(parser, name, FALSE);
+ code = mix_code_file_new_read(name);
+ g_assert(code);
+ g_message("%s: Version: %d.%d", name, mix_code_file_major_version(code),
+ mix_code_file_minor_version(code));
+ mix_short_print(mix_code_file_get_start_addr(code), "Start address: ");
+ g_print("\n");
+ while ( mix_code_file_get_ins(code, &ins) ) {
+ mix_ins_t i;
+ mix_word_to_ins_uncheck(ins.ins, i);
+ mix_short_print(ins.address, "addr: ");
+ g_print(" : ");
+ mix_ins_print(&i);
+ g_print("\n");
+ }
+
+ mix_parser_delete(parser);
+ mix_code_file_delete(code);
+}
+
+int
+main(int argc, char **argv)
+{
+ size_t k;
+
+ INIT_TEST;
+
+ for (k = 0; k < FILE_NO_; ++k)
+ // test_code_(FILES_[k]);
+ ;
+
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/mixlib/testsuite/mix_types_t.c b/mixlib/testsuite/mix_types_t.c
new file mode 100644
index 0000000..be9fb46
--- /dev/null
+++ b/mixlib/testsuite/mix_types_t.c
@@ -0,0 +1,361 @@
+/*----------------------- mix_types_t.c -----------------------------
+ * Tests for mix_types.h
+ * ------------------------------------------------------------------
+*
+** Copyright (C) 1999 Free Software Foundation, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+
+#include <stdlib.h>
+#include <mix_types.h>
+
+/* Define VERBOSE_TEST if you want to get prints of the test */
+/* #define VERBOSE_TEST */
+#include "test.h"
+
+/* compare two words */
+static gboolean
+word_compare_(mix_word_t w1, mix_word_t w2)
+{
+ if ( mix_word_magnitude(w1) == 0 )
+ return ( mix_word_magnitude(w2) == 0 );
+ else
+ return ( w1 == w2 );
+}
+
+
+/* create a word from an array of bytes and check the result */
+static void
+test_word_from_bytes_(mix_word_t *word,
+ mix_byte_t *bytes,
+ unsigned byteno,
+ const char *message)
+{
+ mix_byte_t r;
+ unsigned int k;
+
+ *word = mix_bytes_to_word(bytes,byteno);
+ mix_word_print(*word,message);
+ g_print("\n");
+ for ( k = 5-byteno; k < 5; ++k ) {
+ PRINT_BYTE(r = mix_word_get_byte(*word,k+1));
+ g_print(" (k = %d)\n",k);
+ g_assert( r == bytes[k-5+byteno] );
+ }
+}
+
+
+/* test field access */
+static void
+test_field_access_(mix_fspec_t l, mix_fspec_t r,
+ mix_word_t from, mix_word_t to)
+{
+ mix_fspec_t f = mix_fspec_new(l,r);
+ mix_word_t result;
+
+ PRINT_BYTE(l); g_print(", ");
+ PRINT_BYTE(r); g_print(", ");
+ PRINT_BYTE(f); g_print("\n ");
+ mix_word_print(from, "from: ");
+ mix_word_print(to, " to: ");
+ g_assert( mix_fspec_left(f) == l );
+ g_assert( mix_fspec_right(f) == r );
+ result = mix_word_set_field(f,from,to);
+ mix_word_print(result,"\n\tresult: ");
+ g_assert( mix_word_get_field(f,from) == mix_word_get_field(f,result) );
+ g_print("\n");
+}
+
+/* test word addition */
+static void
+test_word_add_(mix_word_t w1, mix_word_t w2)
+{
+ mix_word_t r;
+
+ r = mix_word_add(w1,w2);
+ mix_word_print(w1,"\n");
+ mix_word_print(w2,NULL);
+ mix_word_print(r," = ");
+ g_assert( word_compare_(mix_word_sub(r,w1), w2) );
+ g_assert( word_compare_(mix_word_sub(r,w2), w1) );
+ /* while asserting the following, take into account that 0 != -0
+ for mix words, although they are logically equivalent
+ */
+ g_assert( word_compare_(mix_word_sub(w1,r), mix_word_negative(w2)) );
+ g_assert( word_compare_(mix_word_sub(w2,r), mix_word_negative(w1)) );
+ g_assert( word_compare_(mix_word_add(w2,w1), r) );
+}
+
+/* test word multiplication */
+static void
+test_word_mul_(mix_word_t w1, mix_word_t w2)
+{
+ mix_word_t h, l, q, r = 0;
+ mix_word_mul(w1,w2,&h,&l);
+ mix_word_print(w1,"\n");
+ mix_word_print(w2,"*");
+ mix_word_print(h,"\n =");
+ mix_word_print(l,NULL);
+ if ( w1 != 0 ) {
+ g_assert( mix_word_div(h,l,w1,&q,&r) == FALSE );
+ g_assert( mix_word_magnitude(r) == 0 );
+ g_assert( q == w2 );
+ } else {
+ g_assert( mix_word_magnitude(l) == 0 && mix_word_magnitude(h) == 0 );
+ }
+ if ( w2 != 0 ) {
+ g_assert( mix_word_div(h,l,w2,&q,&r) == FALSE );
+ g_assert( mix_word_magnitude(r) == 0 );
+ g_assert( q == w1 );
+ } else {
+ g_assert( mix_word_magnitude(l) == 0 && mix_word_magnitude(h) == 0 );
+ }
+
+}
+
+/* test word division */
+static void
+test_word_div_(mix_word_t h, mix_word_t l, mix_word_t by)
+{
+ mix_word_t q,r;
+ gboolean overflow;
+
+ overflow = mix_word_div(h,l,by,&q,&r);
+
+ mix_word_print(h,"\n\n");
+ mix_word_print(l,NULL);
+ mix_word_print(by,"\n div by ");
+
+ if ( !overflow ) {
+ mix_word_t h1, l1, h2;
+ mix_word_print(q,"\n q = ");
+ mix_word_print(r," r = ");
+ mix_word_mul(by,q,&h1,&l1);
+ mix_word_add_and_carry(l1,r,&h2,&l1);
+ h1 = mix_word_add(h1,h2);
+ g_assert( mix_word_magnitude(r) < mix_word_magnitude(by) );
+ g_assert( word_compare_(h1,h) );
+ g_assert( mix_word_magnitude(l1) == mix_word_magnitude(l) );
+ } else
+ g_print("\n\t = overflow");
+
+}
+
+static void
+test_mix_char_(void)
+{
+ mix_char_t mchar;
+ guchar achar;
+ guint k;
+ g_print("\nTesting mix_char_t. Table of mix_chars:\n");
+
+ for (k = 0; k < MIX_CHAR_MAX + 1; ++k) {
+ mchar = k;
+ achar = mix_char_to_ascii(mchar);
+ g_print("%02d: %c, ",k,achar);
+ if ( (k+1)%5 == 0 ) g_print("\n");
+ g_assert( mchar == mix_ascii_to_char(achar) );
+ }
+ g_print("\n");
+}
+
+
+/* main test driver for mix_types.h/c */
+
+int main(int argc, char **argv)
+{
+ unsigned int j,k;
+ mix_byte_t bytes[5] = { 0, 3, 20, 30, 40 };
+ mix_byte_t r;
+ mix_short_t ss[6];
+ mix_word_t words[6];
+
+ INIT_TEST;
+
+ g_print("Testing mix_byte_t arithmetics...\n");
+ PRINT_BYTE(bytes[0]); g_print(", ");
+ PRINT_BYTE(bytes[1]); g_print(", ");
+ PRINT_BYTE(bytes[2]); g_print(", ");
+ PRINT_BYTE(bytes[3]); g_print(", ");
+ PRINT_BYTE(bytes[4]); g_print("\n");
+ PRINT_BYTE(r = mix_byte_add(bytes[1],bytes[2]));
+ g_print("\n"); g_assert(r == 23);
+ PRINT_BYTE(r = mix_byte_add(bytes[3],bytes[4]));
+ g_print("\n"); g_assert(r == 6);
+ PRINT_BYTE(r = mix_byte_sub(bytes[0],bytes[1]));
+ g_print("\n"); g_assert(r == 61);
+ PRINT_BYTE(r = mix_byte_sub(bytes[4],bytes[3]));
+ g_print("\n"); g_assert(r == 10);
+ PRINT_BYTE(r = mix_byte_sub(bytes[1],bytes[4]));
+ g_print("\n"); g_assert(r == 27);
+ PRINT_BYTE(r = mix_byte_mul(bytes[0],bytes[1]));
+ g_print("\n"); g_assert(r == 0);
+ PRINT_BYTE(r = mix_byte_mul(bytes[1],bytes[2]));
+ g_print("\n"); g_assert(r == 60);
+ PRINT_BYTE(r = mix_byte_mul(bytes[1],bytes[4]));
+ g_print("\n"); g_assert(r == 56);
+ PRINT_BYTE(r = mix_byte_mul(bytes[4],bytes[1]));
+ g_print("\n"); g_assert(r == 56);
+ PRINT_BYTE(r = mix_byte_div(bytes[4],bytes[2]));
+ g_print("\n"); g_assert(r == 2);
+ PRINT_BYTE(r = mix_byte_div(bytes[3],bytes[2]));
+ g_print("\n"); g_assert(r == 1);
+
+ test_mix_char_();
+
+ g_print("\nTesting word<->short conversions...");
+ words[0] = mix_bytes_to_word(bytes+1,5);
+ words[1] = mix_word_negative(words[0]);
+ ss[0] = mix_word_to_short(words[0]);
+ ss[1] = mix_word_to_short(words[1]);
+ mix_word_print(words[0],"\nwords[0]=");
+ mix_word_print(words[1],"\nwords[1]=");
+ mix_short_print(ss[0],"\nss[0]=");
+ mix_short_print(ss[1],"\nss[1]=");
+ g_assert(mix_short_is_positive(ss[0]));
+ g_assert(mix_short_is_negative(ss[1]));
+ words[2] = mix_short_to_word(ss[0]);
+ words[3] = mix_short_to_word(ss[1]);
+ mix_word_print(words[2],"\nwords[2]=");
+ mix_word_print(words[3],"\nwords[3]=");
+ g_assert(mix_word_sign(words[0]) == mix_word_sign(words[2]));
+ g_assert(mix_word_sign(words[1]) == mix_word_sign(words[3]));
+ g_assert(mix_short_magnitude(ss[0]) == mix_word_magnitude(words[2]));
+ g_assert(mix_short_magnitude(ss[1]) == mix_word_magnitude(words[3]));
+ g_assert(mix_word_get_byte(words[0],4) == mix_word_get_byte(words[2],4));
+ g_assert(mix_word_get_byte(words[0],5) == mix_word_get_byte(words[2],5));
+ g_assert(mix_word_get_byte(words[1],4) == mix_word_get_byte(words[3],4));
+ g_assert(mix_word_get_byte(words[1],5) == mix_word_get_byte(words[3],5));
+ words[4] = mix_word_extract_field(mix_fspec_new(4,5),words[0]);
+ words[5] = mix_word_extract_field(mix_fspec_new(4,5),words[1]);
+ mix_word_reverse_sign(words[5]);
+ g_assert(words[4] == words[2]);
+ g_assert(words[5] == words[3]);
+
+ g_print("Testing mix_word_t creation and byte access...\n");
+ test_word_from_bytes_(words,bytes,5,"word[0] created from bytes[0-4]");
+ test_word_from_bytes_(words+1,bytes,4,"\nword[1] created from bytes[0-3]");
+ test_word_from_bytes_(words+2,bytes,3,"\nword[2] created from bytes[0-2]");
+ words[3] = mix_word_negative(words[2]);
+ g_assert( mix_word_negative(words[3]) == words[2] );
+ g_assert( mix_word_is_negative(words[3]) && !mix_word_is_negative(words[2]));
+ mix_word_print(words[3],"\nword[3] created from -word[2]");
+ test_word_from_bytes_(words+4,bytes+2,2,"\nword[2] created from bytes[2-3]");
+
+ g_print("\nTesting mix_word_t field access...\n");
+ mix_word_set_byte(words+3,1,12);
+ mix_word_set_byte(words+3,2,58);
+ g_assert( mix_word_get_byte(words[3],1) == 12 );
+ g_assert( mix_word_get_byte(words[3],2) == 58 );
+ test_field_access_(0,5,words[3],words[4]);
+ test_field_access_(1,5,words[3],words[4]);
+ test_field_access_(2,5,words[3],words[4]);
+ test_field_access_(3,5,words[3],words[4]);
+ test_field_access_(4,5,words[3],words[4]);
+ test_field_access_(5,5,words[3],words[4]);
+ test_field_access_(0,0,words[3],words[4]);
+
+ g_print("\n\nTesting mix_word_t arithmetics...\n");
+ words[0] = MIX_WORD_MAX;
+ words[1] = mix_word_negative(words[0]);
+ for ( k = 1; k < 6; ++k ) {
+ mix_word_set_byte(words+2,k,5*k);
+ mix_word_set_byte(words+4,k,10*(5-k));
+ mix_word_set_byte(words+3,k,21 + 3*k);
+ }
+ words[5] = 0;
+
+ g_print("\n***addition***");
+ for ( k = 0; k < 6; ++k )
+ for ( j = 0; j <= k; ++j ) {
+ test_word_add_(words[k],mix_word_negative(words[j]));
+ test_word_add_(words[k],words[j]);
+ }
+ g_print("\n***product***");
+ for ( k = 0; k < 6; ++k )
+ for ( j = 0; j <= k; ++j ) {
+ test_word_mul_(words[k],words[j]);
+ }
+ g_print("\n***division***");
+ for ( k = 0; k < 6; ++k ) {
+ test_word_div_(words[k],0,words[0]);
+ for ( j = 0; j <= k; ++j ) {
+ test_word_div_(k,words[j],words[j]);
+ test_word_div_(0,mix_word_add(mix_word_magnitude(words[j]),j),words[j]);
+ test_word_div_(mix_word_negative(k),words[j],words[j]);
+ }
+ }
+
+ g_print("\nTesting shift operations...\n");
+ for ( k = 0; k < 10; ++k )
+ mix_word_set_byte(words+(k/5),1+(k%5),k+1);
+
+ mix_word_print(words[0],"A = ");
+ mix_word_print(words[1],"X = ");
+ for ( k = 0; k < 11; ++k ) {
+ mix_word_t A, X;
+ unsigned int m;
+
+ mix_word_shift_left(words[0],words[1],k,&A,&X);
+ g_print("\nShift left %d:\n",k);
+ mix_word_print(A,"A ");
+ mix_word_print(X,"X ");
+ for ( m = 0; m < 10 - k; ++m )
+ g_assert( mix_word_get_byte( m < 5 ? A:X, (m%5)+1 ) ==
+ mix_word_get_byte(words[(m+k)/5], ((m+k)%5)+1) );
+ for ( ; m < 10; ++m )
+ g_assert( mix_word_get_byte( m < 5 ? A:X, (m%5)+1 ) == 0 );
+
+ mix_word_shift_right(words[0],words[1],k,&A,&X);
+ g_print("\nShift right %d:\n",k);
+ mix_word_print(A,"A ");
+ mix_word_print(X,"X ");
+ for ( m = 0; m < k; ++m )
+ g_assert( mix_word_get_byte( m < 5 ? A:X, (m%5)+1 ) == 0 );
+ for ( ; m < 10; ++m )
+ g_assert( mix_word_get_byte( m < 5 ? A:X, (m%5)+1 ) ==
+ mix_word_get_byte(words[(m-k)/5], ((m-k)%5)+1) );
+
+ mix_word_shift_left_circular(words[0],words[1],k,&A,&X);
+ g_print("\nShift left circular %d:\n",k);
+ mix_word_print(A,"A ");
+ mix_word_print(X,"X ");
+ for ( m = 0; m < 10 - k; ++m )
+ g_assert( mix_word_get_byte( m < 5 ? A:X, (m%5)+1 ) ==
+ mix_word_get_byte(words[(m+k)/5], ((m+k)%5)+1) );
+ for ( ; m < 10; ++m )
+ g_assert( mix_word_get_byte( m < 5 ? A:X, (m%5)+1 ) ==
+ mix_word_get_byte(words[(m-10+k)/5], 1+((m-10+k)%5)) );
+ mix_word_shift_right_circular(A, X, k, &A, &X);
+ g_print("\nRe-shiftting right...\n");
+ mix_word_print(A, "A ");
+ mix_word_print(X, "X ");
+ g_assert(A == words[0]);
+ g_assert(X == words[1]);
+ }
+
+
+ g_print("\n");
+ return EXIT_SUCCESS;
+}
+
+
+
+
+
+
diff --git a/mixlib/testsuite/mix_vm_ins_t.c b/mixlib/testsuite/mix_vm_ins_t.c
new file mode 100644
index 0000000..55ce7f3
--- /dev/null
+++ b/mixlib/testsuite/mix_vm_ins_t.c
@@ -0,0 +1,500 @@
+/* ---------------------- mix_vm_ins_t.c :
+ * Tests for the virtual machine instruction handlers.
+ * ------------------------------------------------------------------
+** Copyright (C) 2000 Free Software Foundation, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+
+#include <stdlib.h>
+/*#define VERBOSE_TEST*/
+#include "test.h"
+#include "mix_vm.h"
+#include "mix_vm_dump.h"
+
+typedef struct
+{
+ mix_word_t rA_b, rA_a;
+ mix_word_t rX_b, rX_a;
+ mix_short_t rJ_b, rJ_a;
+ mix_short_t rI_b[6], rI_a[6];
+ gboolean over_b, over_a;
+ mix_cmpflag_t cmp_b, cmp_a;
+ mix_address_t begin, end;
+ mix_word_t *cells_b, *cells_a;
+ const mix_ins_t *ins;
+} test_desc_t;
+
+static void
+set_cells_(test_desc_t *t, mix_address_t begin, mix_address_t end)
+{
+ g_assert(begin <= end);
+ t->begin = begin;
+ t->end = end;
+ t->cells_b = g_new(mix_word_t,end-begin);
+ t->cells_a = g_new(mix_word_t,end-begin);
+}
+
+static void
+free_cells_(test_desc_t *t)
+{
+ g_assert(t);
+ g_free(t->cells_a);
+ g_free(t->cells_b);
+ t->cells_a = t->cells_b = NULL;
+ t->begin = t->end = 0;
+}
+
+
+static void
+fill_test_desc_(test_desc_t *t, const mix_vm_t *vm, const mix_ins_t *ins)
+{
+ guint k;
+ g_assert(t);
+ g_assert(vm);
+
+ t->rA_b = t->rA_a = mix_vm_get_rA(vm);
+ t->rX_b = t->rX_a = mix_vm_get_rX(vm);
+ t->rJ_b = t->rJ_a = mix_vm_get_rJ(vm);
+ for ( k = 0; k < 6; ++k )
+ t->rI_b[k] = t->rI_a[k] = mix_vm_get_rI(vm,k+1);
+ t->cmp_b = t->cmp_a = mix_vm_get_cmpflag(vm);
+ t->over_b = t->over_a = mix_vm_get_overflow(vm);
+
+ for (k = 0; k < t->end-t->begin; ++k)
+ t->cells_a[k] = t->cells_b[k] =
+ mix_vm_get_addr_contents(vm,t->begin+k);
+ t->ins = ins;
+}
+
+
+static void
+run_test_(test_desc_t *t, mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ guint k;
+ g_assert(t);
+ g_assert(vm);
+
+ mix_vm_set_rA(vm, t->rA_b);
+ mix_vm_set_rX(vm, t->rX_b);
+ mix_vm_set_rJ(vm, t->rJ_b);
+ for (k = 0; k < 6; ++k) mix_vm_set_rI(vm, k+1, t->rI_b[k]);
+ for (k = t->begin; k < t->end; ++k)
+ mix_vm_set_addr_contents(vm, k, t->cells_b[k-t->begin]);
+ mix_vm_set_cmpflag(vm, t->cmp_b);
+ mix_vm_set_overflow(vm, t->over_b);
+
+ mix_ins_print(t->ins);
+ if (dc) {
+ mix_dump_context_range(dc, t->begin, t->end);
+ mix_vm_dump(vm,dc);
+ }
+ k = mix_vm_exec_ins(vm, t->ins);
+ if (dc) mix_vm_dump(vm, dc);
+ g_assert(k == TRUE);
+ g_assert(mix_vm_get_rA(vm) == t->rA_a);
+ g_assert(mix_vm_get_rX(vm) == t->rX_a);
+ for (k = 0; k < 6; ++k) g_assert(mix_vm_get_rI(vm, k+1) == t->rI_a[k]);
+ g_assert(mix_vm_get_cmpflag(vm) == t->cmp_a);
+ g_assert(mix_vm_get_overflow(vm) == t->over_a);
+ for (k = t->begin; k < t->end; ++k)
+ g_assert(mix_vm_get_addr_contents(vm, k) == t->cells_a[k-t->begin]);
+}
+
+
+
+static void
+test_arithmetics_(mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ test_desc_t test;
+ mix_ins_t ins;
+
+ g_print("\nTesting arithmetic instructions...\n");
+ mix_vm_reset(vm);
+ mix_ins_fill_from_id(ins,mix_ADD);
+ ins.index = 0;
+ ins.address = 1000;
+ mix_vm_set_rA(vm,mix_word_new_b(19,18,1,2,22));
+ mix_vm_set_addr_contents(vm,1000,mix_word_new_b(1,36,5,0,50));
+ set_cells_(&test,1000,1001);
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(20,54,6,3,8);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins,mix_SUB);
+ mix_vm_set_rA(vm,mix_word_new_bn(19,18,0,0,9));
+ mix_vm_set_addr_contents(vm,1000,mix_word_new_bn(31,16,2,22,0));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(11,62,2,21,55);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins,mix_MUL);
+ mix_vm_set_rA(vm,mix_word_new_b(1,1,1,1,1));
+ mix_vm_set_addr_contents(vm,1000, mix_word_new_b(1,1,1,1,1));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(0,1,2,3,4);
+ test.rX_a = mix_word_new_b(5,4,3,2,1);
+ run_test_(&test, vm, dc);
+
+ ins.fspec = mix_fspec_new(1,1);
+ mix_vm_set_rA(vm,mix_word_new_bn(0,0,0,1,48));
+ mix_vm_set_addr_contents(vm,1000,mix_word_new_bn(2,16,2,22,0));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = MIX_WORD_MINUS_ZERO;
+ test.rX_a = mix_word_new_bn(0,0,0,3,32);
+ run_test_(&test, vm, dc);
+
+ mix_vm_set_rA(vm,mix_word_new_bn(0,0,0,1,48));
+ mix_vm_set_addr_contents(vm,1000,mix_word_new_b(2,0,34,33,1));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = MIX_WORD_MINUS_ZERO;
+ test.rX_a = mix_word_new_bn(0,0,0,3,32);
+ run_test_(&test, vm, dc);
+
+ ins.fspec = mix_fspec_new(0,5);
+ mix_vm_set_rA(vm,mix_word_new_bn(50,0,1,48,4));
+ mix_vm_set_addr_contents(vm,1000,mix_word_new_bn(2,0,0,0,0));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(1,36,0,3,32);
+ test.rX_a = mix_word_new_b(8,0,0,0,0);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins,mix_DIV);
+ mix_vm_set_rA(vm,MIX_WORD_ZERO);
+ mix_vm_set_rX(vm,mix_word_new_b(0,0,0,0,17));
+ mix_vm_set_addr_contents(vm,1000, mix_word_new_b(0,0,0,0,3));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(0,0,0,0,5);
+ test.rX_a = mix_word_new_b(0,0,0,0,2);
+ run_test_(&test, vm, dc);
+
+ mix_vm_set_rA(vm,MIX_WORD_ZERO);
+ mix_vm_set_rX(vm,mix_word_new_bn(0,0,0,0,17));
+ mix_vm_set_addr_contents(vm,1000, mix_word_new_b(0,0,0,0,3));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(0,0,0,0,5);
+ test.rX_a = mix_word_new_b(0,0,0,0,2);
+ run_test_(&test, vm, dc);
+
+ mix_vm_set_rA(vm, MIX_WORD_MINUS_ZERO);
+ mix_vm_set_rX(vm, mix_word_new_b(19,19,0,3,1));
+ mix_vm_set_addr_contents(vm,1000, mix_word_new_bn(0,0,0,2,0));
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = mix_word_new_b(0,9,41,32,1);
+ test.rX_a = mix_word_new_bn(0,0,0,1,1);
+ run_test_(&test, vm, dc);
+
+ free_cells_(&test);
+}
+
+static void
+test_shift_(mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ test_desc_t test;
+ mix_ins_t ins;
+
+ g_print("Testing shift instructions...\n");
+ mix_vm_reset(vm);
+ set_cells_(&test,0,0);
+ fill_test_desc_(&test,vm,&ins);
+ mix_ins_fill_from_id(ins,mix_SRAX);
+ ins.index = 0;
+ ins.address = 1;
+ test.rA_b = mix_word_new_b(1,2,3,4,5);
+ test.rX_b = mix_word_new_bn(6,7,8,9,10);
+ test.rA_a = mix_word_new_b(0,1,2,3,4);
+ test.rX_a = mix_word_new_bn(5,6,7,8,9);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_SLA);
+ ins.address = 2;
+ fill_test_desc_(&test, vm, &ins);
+ test.rA_a = mix_word_new_b(2,3,4,0,0);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_SRC);
+ ins.address = 4;
+ fill_test_desc_(&test, vm, &ins);
+ test.rA_a = mix_word_new_b(6,7,8,9,2);
+ test.rX_a = mix_word_new_bn(3,4,0,0,5);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_SRA);
+ ins.address = 2;
+ fill_test_desc_(&test, vm, &ins);
+ test.rA_a = mix_word_new_b(0,0,6,7,8);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_SLC);
+ ins.address = 501;
+ fill_test_desc_(&test, vm, &ins);
+ test.rA_a = mix_word_new_b(0,6,7,8,3);
+ test.rX_a = mix_word_new_bn(4,0,0,5,0);
+ run_test_(&test, vm, dc);
+}
+
+static void
+test_spc_(mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ test_desc_t test;
+ mix_ins_t ins;
+
+ g_print("Testing special instructions...\n");
+ mix_vm_reset(vm);
+ set_cells_(&test,0,0);
+ fill_test_desc_(&test,vm,&ins);
+ mix_ins_fill_from_id(ins,mix_NUM);
+ ins.index = 0;
+ ins.address = 0;
+ test.rA_b = mix_word_new_bn(0,0,31,32,39);
+ test.rX_b = mix_word_new_b(37,57,47,30,30);
+ test.rA_a = mix_word_negative(12977700);
+ test.rX_a = test.rX_b;
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_INCA);
+ ins.address = 1;
+ fill_test_desc_(&test, vm, &ins);
+ test.rA_a = mix_word_negative(12977699);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_CHAR);
+ fill_test_desc_(&test, vm, &ins);
+ test.rA_a = mix_word_new_bn(30,30,31,32,39);
+ test.rX_a = mix_word_new_b(37,37,36,39,39);
+ run_test_(&test, vm, dc);
+
+ mix_ins_fill_from_id(ins, mix_HLT);
+ fill_test_desc_(&test, vm, &ins);
+ run_test_(&test, vm, dc);
+ g_assert(mix_vm_is_halted(vm));
+
+}
+
+static void
+test_move_(mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ test_desc_t test;
+ mix_ins_t ins;
+ guint k;
+
+ g_print("Testing move instruction...\n");
+ mix_vm_reset(vm);
+ set_cells_(&test,0,10);
+ fill_test_desc_(&test,vm,&ins);
+ mix_ins_fill_from_id(ins,mix_MOVE);
+
+ ins.index = 0;
+ ins.address = 0;
+ ins.fspec = 5;
+ for ( k = 0; k < 5; ++k )
+ test.cells_b[k] = test.cells_a[k+5] = test.cells_a[k] =mix_word_new(100*k);
+
+ test.rI_b[0] = 5;
+ test.rI_a[0] = 10;
+ run_test_(&test,vm,dc);
+
+ free_cells_(&test);
+}
+
+
+
+static void
+test_load_(mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ test_desc_t test;
+ mix_ins_t ins;
+ mix_ins_id_t ids[4] = {mix_LDA, mix_LDX, mix_LDAN, mix_LDXN};
+ mix_word_t r_a[14] = { mix_word_new_bn(1,16,3,5,4),
+ mix_word_new_b(1,16,3,5,4),
+ mix_word_new_b(0,0,3,5,4),
+ mix_word_new_bn(0,0,1,16,3),
+ mix_word_new_b(0,0,0,0,5),
+ MIX_WORD_MINUS_ZERO,
+ mix_word_new_b(0,0,0,0,1),
+ mix_word_new_b(1,16,3,5,4),
+ mix_word_new_b(1,16,3,5,4),
+ mix_word_new_b(0,0,3,5,4),
+ mix_word_new_b(0,0,1,16,3),
+ mix_word_new_b(0,0,0,0,5),
+ MIX_WORD_ZERO,
+ mix_word_new_b(0,0,0,0,1)};
+ mix_fspec_t fs[11] = {5,13,29,3,36,0,9,0,0,0,0};
+ mix_address_t a_a[11] = { MIX_SHORT_MINUS_ZERO,
+ mix_short_new_bn(0,1),
+ mix_short_new_bn(1,16),
+ mix_short_new_bn(16,3),
+ mix_short_new_bn(3,5),
+ mix_short_new_bn(5,4),
+ mix_short_new_b(1,16),
+ mix_short_new_b(16,3),
+ mix_short_new_b(5,4),
+ mix_short_new_b(5,4),
+ mix_short_new_b(3,5)};
+ mix_word_t val = mix_word_new_bn(1,16,3,5,4);
+ gint j;
+
+ g_print("Testing load instructions...\n");
+ set_cells_(&test,2000,2001);
+ ins.index = 1;
+ ins.address = mix_short_negative(50);
+
+ mix_vm_reset(vm);
+ mix_vm_set_addr_contents(vm, 2000, val);
+
+ for (j = 0; j < 4; ++j)
+ {
+ gint k;
+ mix_ins_fill_from_id(ins,ids[j]);
+ for ( k = 0; k < 7; ++k ) {
+ fill_test_desc_(&test,vm,&ins);
+ ins.fspec = fs[k];
+ switch (ids[j])
+ {
+ case mix_LDA: test.rA_a = r_a[k]; break;
+ case mix_LDX: test.rX_a = r_a[k]; break;
+ case mix_LDAN: test.rA_a = r_a[k+7]; break;
+ case mix_LDXN: test.rX_a = r_a[k+7]; break;
+ default: g_assert_not_reached();
+ }
+ test.rI_b[0] = test.rI_a[0] = 2050;
+ run_test_(&test, vm, dc);
+ }
+ }
+ ins.index = 0;
+ ins.address = 2000;
+ fs[0] = 0; fs[1] = 1; fs[2] = 2; fs[3] = 3; fs[4] = 4; fs[5] = 5;
+ fs[6] = 10; fs[7] = 11; fs[8] = 37; fs[9] = 29; fs[10] = 12;
+
+ mix_vm_reset(vm);
+ mix_vm_set_addr_contents(vm, 2000, val);
+ for ( j = 0; j < 14; j++ )
+ {
+ guint k;
+ if (j == 6 || j == 7 ) continue; /* mix_LDX, mix_LDAN */
+ mix_ins_fill_from_id(ins, mix_LD1 + j);
+ for (k = 0; k < 11; ++k)
+ {
+ fill_test_desc_(&test, vm, &ins);
+ ins.fspec = fs[k];
+ if ( j < 6 )
+ test.rI_a[j] = a_a[k];
+ else /* mix_LDiN */
+ test.rI_a[j-8] = mix_short_magnitude(a_a[k]);
+ run_test_(&test, vm, dc);
+ }
+ }
+
+ free_cells_(&test);
+}
+
+
+static void
+test_store_(mix_vm_t *vm, mix_dump_context_t *dc)
+{
+ test_desc_t test;
+ mix_ins_t ins;
+ mix_word_t reg = mix_word_new_b(6,7,8,9,0);
+ mix_word_t add = mix_word_new_bn(1,2,3,4,5);
+ mix_word_t addr[6] = { mix_word_new_b(6,7,8,9,0),
+ mix_word_new_bn(6,7,8,9,0),
+ mix_word_new_bn(1,2,3,4,0),
+ mix_word_new_bn(1,0,3,4,5),
+ mix_word_new_bn(1,9,0,4,5),
+ mix_word_new_b(0,2,3,4,5)};
+ mix_word_t addri[6] = { mix_word_new_b(0,0,0,9,0),
+ mix_word_new_bn(0,0,0,9,0),
+ mix_word_new_bn(1,2,3,4,0),
+ mix_word_new_bn(1,0,3,4,5),
+ mix_word_new_bn(1,9,0,4,5),
+ mix_word_new_b(0,2,3,4,5)};
+ mix_word_t addrz[6] = { mix_word_new_b(0,0,0,0,0),
+ mix_word_new_bn(0,0,0,0,0),
+ mix_word_new_bn(1,2,3,4,0),
+ mix_word_new_bn(1,0,3,4,5),
+ mix_word_new_bn(1,0,0,4,5),
+ mix_word_new_b(0,2,3,4,5)};
+ mix_fspec_t fs[6] = {5,13,45,18,19,1};
+ gint i,j;
+
+ g_print("Testing store instructions...\n");
+
+ set_cells_(&test,2000,2001);
+ ins.index = 0;
+ ins.address = 2000;
+
+ mix_vm_reset(vm);
+ fill_test_desc_(&test,vm,&ins);
+ test.rA_a = test.rA_b = test.rX_a = test.rX_b = reg;
+ test.rJ_a = test.rJ_b = mix_word_to_short(reg);
+ for (j = 0; j < 6; ++j)
+ test.rI_a[j] = test.rI_b[j] = test.rJ_a;
+ test.cells_b[0] = add;
+
+ for (i = 0; i < 10; ++i)
+ {
+ mix_ins_fill_from_id(ins,mix_STA+i);
+ for (j = 0; j < 6; ++j)
+ {
+ ins.fspec = fs[j];
+ if (i == 0 || i == 7 ) /* mix_STA, mix_STX */
+ test.cells_a[0] = addr[j];
+ else if ( i < 9 ) /* mix_STi, mix_STJ */
+ test.cells_a[0] = addri[j];
+ else /* mix_STZ */
+ test.cells_a[0] = addrz[j];
+ run_test_(&test,vm,dc);
+ }
+ }
+
+ free_cells_(&test);
+}
+
+
+
+int
+main(int argc, const char **argv)
+{
+ mix_vm_t *vm;
+ mix_dump_context_t *dc;
+
+ INIT_TEST;
+
+ vm = mix_vm_new();
+
+#ifdef VERBOSE_TEST
+ dc = mix_dump_context_new(MIX_DUMP_DEF_CHANNEL, 0, 0, MIX_DUMP_ALL);
+#else
+ dc = NULL;
+#endif
+
+ test_arithmetics_(vm, dc);
+ test_shift_(vm, dc);
+ test_spc_(vm,dc);
+ test_move_(vm,dc);
+ test_load_(vm,dc);
+ test_store_(vm,dc);
+
+ mix_vm_delete(vm);
+
+#ifdef VERBOSE_TEST
+ mix_dump_context_delete(dc);
+#endif
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/mixlib/testsuite/test.h b/mixlib/testsuite/test.h
new file mode 100644
index 0000000..6bf6306
--- /dev/null
+++ b/mixlib/testsuite/test.h
@@ -0,0 +1,44 @@
+/*
+** Copyright (C) 1999 Free Software Foundation, Inc.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+/* Common definitions for test programs */
+
+#ifndef TEST_H
+#define TEST_H
+
+#include <glib.h>
+#include <mix.h>
+
+#define PRINT_BYTE(byte) g_print("%s = %02d",#byte,byte)
+
+#ifdef VERBOSE_TEST /* get printed information */
+#define INIT_TEST \
+ do { g_set_print_handler(NULL); mix_init_lib(); } while(FALSE);
+#else /* no printed information */
+static void
+dummy_print_f_(const gchar *m)
+{
+ /* no output */
+}
+#define INIT_TEST \
+do { g_set_print_handler(dummy_print_f_); mix_init_lib(); } while(FALSE);
+#endif /* VERBOSE_TEST */
+
+
+#endif /* TEST_H */
diff --git a/mixlib/xmix_device.c b/mixlib/xmix_device.c
new file mode 100644
index 0000000..4754015
--- /dev/null
+++ b/mixlib/xmix_device.c
@@ -0,0 +1,131 @@
+/* -*-c-*- -------------- xmix_device.c :
+ * Implementation of the functions declared in xmix_device.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: "01/03/02 23:14:57 jose"
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include "xmix_device.h"
+
+const char *DEV_EXT_ = ".dev";
+
+const char *DEF_NAMES_[] = {
+ "tape0", "tape1", "tape2", "tape3", "tape4", "tape5", "tape6", "tape7",
+ "disk0", "disk1", "disk2", "disk3", "disk4", "disk5", "disk6", "disk7",
+ "cardrd", "cardwr", "printer", "console", "paper"
+};
+
+const size_t SIZES_[] = {
+ 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100, 100,
+ 16, 16, 24, 14, 14
+};
+
+const mix_device_mode_t MODES_[] = {
+ mix_dev_BIN, mix_dev_BIN, mix_dev_BIN, mix_dev_BIN, mix_dev_BIN,
+ mix_dev_BIN, mix_dev_BIN, mix_dev_BIN, mix_dev_BIN, mix_dev_BIN,
+ mix_dev_BIN, mix_dev_BIN, mix_dev_BIN, mix_dev_BIN, mix_dev_BIN,
+ mix_dev_BIN, mix_dev_CHAR, mix_dev_CHAR, mix_dev_CHAR, mix_dev_CHAR,
+ mix_dev_CHAR
+};
+
+const mix_fmode_t FMODES_[] = {
+ mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT,
+ mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT,
+ mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT,
+ mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT, mix_io_RDWRT,
+ mix_io_READ, mix_io_WRITE, mix_io_WRITE, mix_io_WRITE, mix_io_WRITE
+};
+
+/*
+ Write a block to the device.
+*/
+static gboolean
+write_ (mix_device_t *dev, const mix_word_t *block)
+{
+ gboolean result;
+
+ if (FMODES_[dev->type] == mix_io_READ) return FALSE;
+ if (MODES_[dev->type] == mix_dev_CHAR)
+ result = mix_io_write_word_array_as_char (GET_CHANNEL_ (dev),
+ block, SIZES_[dev->type]);
+ else
+ result = mix_io_write_word_array (GET_CHANNEL_ (dev),
+ block, SIZES_[dev->type]);
+ if (result && mix_device_mode(dev) == mix_dev_CHAR)
+ putc ('\n', mix_io_to_FILE (GET_CHANNEL_ (dev)));
+
+ fflush (mix_io_to_FILE (GET_CHANNEL_ (dev)));
+
+ return result;
+}
+
+static gboolean
+read_ (mix_device_t *dev, mix_word_t *block)
+{
+ if (FMODES_[dev->type] == mix_io_WRITE) return FALSE;
+ if (MODES_[dev->type] == mix_dev_CHAR)
+ return mix_io_read_word_array_as_char (GET_CHANNEL_ (dev),
+ block, SIZES_[dev->type]);
+ else
+ return mix_io_read_word_array (GET_CHANNEL_ (dev),
+ block, SIZES_[dev->type]);
+}
+
+static gboolean
+ioc_ (mix_device_t *dev, mix_short_t arg)
+{
+ int m;
+ FILE *file;
+
+ m = mix_short_magnitude(arg);
+ if (mix_short_is_negative(arg)) m = -m;
+ m *= sizeof (mix_word_t) * SIZES_[dev->type];
+ file = mix_io_to_FILE (GET_CHANNEL_(dev));
+
+ if (dev->type >= mix_dev_TAPE_0 && dev->type <= mix_dev_TAPE_7)
+ {
+ if (m == 0) rewind (file);
+ else fseek (file, m, SEEK_CUR);
+ }
+ if (dev->type >= mix_dev_DISK_0 && dev->type <= mix_dev_DISK_7)
+ {
+ g_return_val_if_fail (m == 0, FALSE);
+ // position disk
+ }
+ if (dev->type == mix_dev_PAPER_TAPE)
+ {
+ g_return_val_if_fail (m == 0, FALSE);
+ rewind (file);
+ }
+ return TRUE;
+}
+
+static gboolean
+busy_ (const mix_device_t *dev)
+{
+ return (!mix_io_is_ready (GET_CHANNEL_(dev)));
+}
+
+static mix_device_vtable_t VTABLE_ = {
+ write_, read_, ioc_, busy_
+};
+
+const mix_device_vtable_t * DEF_DEV_VTABLE_ = &VTABLE_;
diff --git a/mixlib/xmix_device.h b/mixlib/xmix_device.h
new file mode 100644
index 0000000..45fd7d3
--- /dev/null
+++ b/mixlib/xmix_device.h
@@ -0,0 +1,77 @@
+/* -*-c-*- ---------------- xmix_device.h :
+ * Protected declarations for mix_device_t
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/03/02 01:15:22 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef XMIX_DEVICE_H
+#define XMIX_DEVICE_H
+
+#include "mix_file.h"
+#include "mix_device.h"
+
+/* table of overridable device operations */
+typedef gboolean (*mix_dev_write_func_t) (mix_device_t *, const mix_word_t *);
+typedef gboolean (*mix_dev_read_func_t) (mix_device_t *, mix_word_t *);
+typedef gboolean (*mix_dev_ioc_func_t) (mix_device_t *, mix_short_t);
+typedef gboolean (*mix_dev_busy_func_t) (const mix_device_t *);
+
+typedef struct mix_device_vtable_t
+{
+ mix_dev_write_func_t write;
+ mix_dev_read_func_t read;
+ mix_dev_ioc_func_t ioc;
+ mix_dev_busy_func_t busy;
+} mix_device_vtable_t;
+
+/* default vtable */
+extern const mix_device_vtable_t *DEF_DEV_VTABLE_;
+
+/*
+ Actual definition of a mix device, which can be cast to
+ a mix file.
+*/
+struct mix_device_t
+{
+ mix_iochannel_t *file;
+ mix_device_type_t type;
+ const mix_device_vtable_t *vtable;
+};
+
+#define GET_CHANNEL_(dev) (dev->file)
+#define GET_FILE_(dev) ((mix_file_t *)(dev->file))
+
+/* default extension for device files */
+extern const char *DEV_EXT_;
+/* default names for device files */
+extern const char *DEF_NAMES_[];
+/* block sizes for devices */
+extern const size_t SIZES_[];
+/* io modes for devices */
+extern const mix_device_mode_t MODES_[];
+/* files modes for devices */
+extern const mix_fmode_t FMODES_[];
+
+
+
+
+#endif /* XMIX_DEVICE_H */
+
diff --git a/mixlib/xmix_eval.h b/mixlib/xmix_eval.h
new file mode 100644
index 0000000..b43803a
--- /dev/null
+++ b/mixlib/xmix_eval.h
@@ -0,0 +1,55 @@
+/* -*-c-*- ---------------- xmix_eval.h :
+ * Definition of opaque types in mix_eval.h
+ * ------------------------------------------------------------------
+ * Last change: Time-stamp: <01/02/20 00:25:14 jose>
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef XMIX_EVAL_H
+#define XMIX_EVAL_H
+
+#include "mix_eval.h"
+
+/* the evaluator type */
+struct mix_eval_t
+{
+ mix_symbol_table_t *table; /* symbol table */
+ gboolean towner; /* true if owns the table */
+ mix_eval_result_t result; /* last evaluation result */
+ gint errpos; /* location of last error */
+ mix_word_t value; /* last computed value */
+};
+
+/* flex scanner data/result struct */
+typedef struct mix_eval_data_
+{
+ gchar *expr;
+ const mix_symbol_table_t *table;
+ mix_word_t value;
+ mix_short_t loc;
+ gint errpos;
+} mix_eval_data_;
+
+/* flex scanner prototype */
+extern
+mix_eval_result_t mix_eval_expr (mix_eval_data_ *data);
+
+#endif /* XMIX_EVAL_H */
+
diff --git a/mixlib/xmix_io.c b/mixlib/xmix_io.c
new file mode 100644
index 0000000..7511949
--- /dev/null
+++ b/mixlib/xmix_io.c
@@ -0,0 +1,57 @@
+/* -*-c-*- ------------------ xmix_io.c :
+ * Implementation of the functions declared in xmix_io.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "xmix_io.h"
+
+const char *io_OPENTYPE_[5] = { "r", "w", "w+", "a", "a+" };
+
+
+/* initialise a mix_iochannel from a file descriptor */
+gboolean
+io_init_from_fdesc_(mix_iochannel_t *ioc, int fdesc)
+{
+ FILE *file;
+ mix_fmode_t mode;
+ int flags = fcntl(fdesc, F_GETFL);
+
+ if ( (flags&O_RDONLY) == O_RDONLY )
+ mode = mix_io_READ;
+ else if ( (flags&O_WRONLY) == O_WRONLY )
+ mode = mix_io_WRITE;
+ else if ( (flags&O_RDWR) == O_RDWR )
+ mode = mix_io_RDWRT;
+ else
+ return FALSE;
+
+ file = fdopen(fdesc, fmode_to_type_(mode));
+ g_return_val_if_fail(file != NULL, FALSE);
+
+ io_init_from_file_(ioc, file);
+
+ return TRUE;
+}
+
+
+
diff --git a/mixlib/xmix_io.h b/mixlib/xmix_io.h
new file mode 100644
index 0000000..19cbe04
--- /dev/null
+++ b/mixlib/xmix_io.h
@@ -0,0 +1,64 @@
+/* -*-c-*- ------------------ xmix_io.h :
+ * Implementation of mix_iochannel_t and mix_file_t
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef XMIX_IOCHANNEL_H
+#define XMIX_IOCHANNEL_H
+
+#include <stdio.h>
+#include "mix_io.h"
+
+/* the actual definition of mix_iochannel_t */
+struct mix_iochannel_t
+{
+ FILE *file;
+};
+
+
+extern const char * io_OPENTYPE_[5];
+
+#define fmode_to_type_(mode) ( (mode) < 6 ? io_OPENTYPE_[(mode)]:NULL )
+
+/* initialisation */
+extern gboolean
+io_init_from_fdesc_(mix_iochannel_t *ioc, int fdesc);
+
+#define io_init_from_file_(ioc,f) (ioc)->file = f
+
+#define io_close_(ioc) fclose((ioc)->file)
+
+/* write/read data */
+#define write_data_(ioc,data,no) \
+ ( (no) == fwrite((const void*)(data), sizeof(*(data)), (no), (ioc)->file) )
+
+#define read_data_(ioc,data,no) \
+ ( (no) == fread((void*)(data), sizeof(*(data)), (no), (ioc)->file) )
+
+/* state */
+#define is_eof_(ioc) ( feof((ioc)->file) != 0 )
+#define is_ready_(ioc) ( ferror((ioc)->file) == 0 )
+
+/* conversions */
+#define io_get_FILE_(ioc) (MIX_IOCHANNEL(ioc))->file
+
+
+#endif /* XMIX_IOCHANNEL_H */
+
diff --git a/mixlib/xmix_parser.h b/mixlib/xmix_parser.h
new file mode 100644
index 0000000..1915a0d
--- /dev/null
+++ b/mixlib/xmix_parser.h
@@ -0,0 +1,107 @@
+/* -*-c-*- ---------------- xmix_parser.h :
+ * Declarations for the implementation of mix_parser_t
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef XMIX_PARSER_H
+#define XMIX_PARSER_H
+
+#include "mix_ins.h"
+#include "mix_file.h"
+#include "mix_symbol_table.h"
+#include "mix_parser.h"
+
+/* mix_parser_t definition */
+struct mix_parser_t
+{
+ mix_file_t *in_file; /* the source file to be compiled */
+ mix_symbol_table_t *symbol_table;
+ mix_symbol_table_t *ls_table; /* literal strings symbols */
+ guint cur_ls; /* current literal string symbol */
+ GHashTable *future_refs; /* a map from symbol name to list of addresses */
+ GTree *ins_table; /* a table of compiled instructions */
+ mix_address_t loc_count; /* current memory location during compilation */
+ mix_parser_err_t status; /* outcome of compilation */
+ guint err_line; /* line of the last error */
+ guint err_count; /* no. of errors during compilation */
+ guint warn_count; /* no. of warnings during compilation */
+ mix_address_t start; /* start address of the compiled code */
+};
+
+/* each node of the ins_table stores a mix_word_t with the instruction
+ and a source code line (for debugging and listing)
+*/
+typedef struct ins_node_
+{
+ mix_word_t ins;
+ guint lineno;
+} ins_node_;
+
+
+/* functions to manipulate mix_parser_t during compilation */
+
+/* access loc counter */
+#define get_ploc_(parser) ((parser)->loc_count)
+
+/* symbol table */
+/* Define a new symbol with given value
+ * and update previously set refs to this symbol
+ */
+extern mix_parser_err_t
+mix_parser_define_symbol_value (mix_parser_t *parser, const gchar *name,
+ mix_word_t value);
+
+/* Define a new symbol with value equal to the current loc_count
+ * and update previously set refs to this symbol
+ */
+extern mix_parser_err_t
+mix_parser_define_symbol_here(mix_parser_t *parser, const gchar *name);
+
+/* Set a reference to future symbol here */
+extern void
+mix_parser_set_future_ref(mix_parser_t *parser, const gchar *name);
+
+/* Redefine the value of a local symbol as the current loc_count */
+extern void
+mix_parser_manage_local_symbol(mix_parser_t *parser, const gchar *name,
+ mix_short_t value);
+
+/* Literal strings symbols */
+extern void
+mix_parser_define_ls (mix_parser_t *parser, mix_word_t value);
+
+/* Compilation */
+/* Add instruction with address the current loc_count */
+extern void
+mix_parser_add_ins(mix_parser_t *parser, const mix_ins_t *new_ins,
+ guint lineno);
+extern void
+mix_parser_add_raw(mix_parser_t *parser, mix_word_t word, guint lineno);
+
+/* Error handling */
+extern void
+mix_parser_log_error(mix_parser_t *parser, mix_parser_err_t error,
+ gint lineno, const gchar *comment, gboolean warn);
+
+
+
+
+#endif /* XMIX_PARSER_H */
+
diff --git a/mixlib/xmix_vm.c b/mixlib/xmix_vm.c
new file mode 100644
index 0000000..e614cb4
--- /dev/null
+++ b/mixlib/xmix_vm.c
@@ -0,0 +1,567 @@
+/* ---------------------- xmix_vm.c :
+ * Implementation of the functions declared in xmix_vm.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+
+#include "xmix_vm.h"
+
+/* auxiliar functions */
+G_INLINE_FUNC mix_address_t
+get_M_(const mix_vm_t *vm, const mix_ins_t *ins);
+G_INLINE_FUNC mix_word_t
+get_V_(const mix_vm_t *vm, const mix_ins_t *ins);
+G_INLINE_FUNC mix_device_t *
+get_dev_ (mix_vm_t *vm, mix_fspec_t type);
+
+G_INLINE_FUNC mix_address_t
+get_M_(const mix_vm_t *vm, const mix_ins_t *ins)
+{
+ if ( ins->index == 0 )
+ return ins->address;
+ else
+ return mix_short_add(ins->address,
+ mix_word_to_short_fast(get_rI_(vm, ins->index)));
+}
+
+G_INLINE_FUNC mix_word_t
+get_V_(const mix_vm_t *vm, const mix_ins_t *ins)
+{
+ return mix_word_get_field(ins->fspec, get_cell_(vm, get_M_(vm,ins)));
+}
+
+G_INLINE_FUNC mix_device_t *
+get_dev_ (mix_vm_t *vm, mix_fspec_t type)
+{
+ if (type >= BD_NO_) return NULL;
+ if (vm->devices[type] == NULL)
+ vm->devices[type] = mix_device_new (type);
+ return vm->devices[type];
+}
+
+/* Instruction handlers */
+
+static gboolean
+nop_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert(ins->opcode == mix_opNOP);
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+add_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_word_t val = get_V_(vm, ins);
+ g_assert(ins->opcode == mix_opADD || ins->opcode == mix_opSUB);
+ if ( ins->opcode == mix_opSUB ) mix_word_reverse_sign(val);
+ if ( mix_word_add_and_carry(get_rA_(vm), val, NULL, &get_rA_(vm)) )
+ set_over_(vm,TRUE);
+ inc_loc_(vm);
+ return TRUE;
+}
+
+
+static gboolean
+mul_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert(ins->opcode == mix_opMUL);
+ mix_word_mul(get_rA_(vm), get_V_(vm,ins), &get_rA_(vm), &get_rX_(vm));
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+div_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert(ins->opcode == mix_opDIV);
+ if ( mix_word_div(get_rA_(vm), get_rX_(vm), get_V_(vm,ins),
+ &get_rA_(vm), &get_rX_(vm)) )
+ set_over_(vm,TRUE);
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+spc_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert(ins->opcode == mix_opSPC);
+
+ switch (mix_ins_id_from_ins(*ins)) {
+ case mix_HLT: halt_(vm, TRUE); break;
+ case mix_CHAR:
+ {
+ guint32 num = mix_word_magnitude(get_rA_(vm));
+ mix_char_t z = mix_ascii_to_char('0');
+ guint i;
+ for (i = 5; 0 < i; --i, num /= 10)
+ mix_word_set_byte(&get_rX_(vm), i, z + num % 10);
+ for (i = 5; 0 < i; --i, num /= 10)
+ mix_word_set_byte(&get_rA_(vm), i, z + num % 10);
+ break;
+ }
+ case mix_NUM:
+ {
+ guint i;
+ mix_word_t num = MIX_WORD_ZERO;
+ mix_word_t ten = 10;
+ for (i = 1; i <= 5; ++i) {
+ mix_word_mul(ten, num, NULL, &num);
+ mix_word_add_and_carry(num, mix_word_get_byte(get_rA_(vm),i)%10,
+ NULL, &num);
+ }
+ for (i = 1; i <= 5; ++i) {
+ mix_word_mul(ten, num, NULL, &num);
+ mix_word_add_and_carry(num, mix_word_get_byte(get_rX_(vm),i)%10,
+ NULL, &num);
+ }
+ set_rA_(vm,
+ mix_word_is_negative(get_rA_(vm)) ? mix_word_negative(num):num);
+ break;
+ }
+ default: return FALSE;
+ }
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+sla_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_short_t n = get_M_(vm,ins);
+
+ g_assert(ins->opcode == mix_opSLx);
+ g_return_val_if_fail(mix_short_is_positive(n), FALSE);
+
+ switch ( mix_ins_id_from_ins(*ins) ) {
+ case mix_SLA:
+ mix_word_shift_left(get_rA_(vm), MIX_WORD_ZERO, n, &get_rA_(vm), NULL);
+ break;
+ case mix_SRA:
+ mix_word_shift_right(get_rA_(vm), MIX_WORD_ZERO, n, &get_rA_(vm), NULL);
+ break;
+ case mix_SLAX:
+ mix_word_shift_left(get_rA_(vm), get_rX_(vm), n,
+ &get_rA_(vm), &get_rX_(vm));
+ break;
+ case mix_SRAX:
+ mix_word_shift_right(get_rA_(vm), get_rX_(vm), n,
+ &get_rA_(vm), &get_rX_(vm));
+ break;
+ case mix_SLC:
+ mix_word_shift_left_circular(get_rA_(vm), get_rX_(vm), n,
+ &get_rA_(vm), &get_rX_(vm));
+ break;
+ case mix_SRC:
+ mix_word_shift_right_circular(get_rA_(vm), get_rX_(vm), n,
+ &get_rA_(vm), &get_rX_(vm));
+ break;
+ default:
+ return FALSE;
+ }
+
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+mov_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_short_t from = get_M_(vm,ins),
+ to = mix_word_to_short_fast(get_rI_(vm,1));
+ guint k, delta = ins->fspec;
+
+ g_assert(ins->opcode == mix_opMOVE);
+ g_return_val_if_fail(mix_short_is_positive(from), FALSE);
+ g_return_val_if_fail(mix_short_is_positive(to), FALSE);
+ g_return_val_if_fail(MEMOK_(from + delta -1), FALSE);
+ g_return_val_if_fail(MEMOK_(to + delta - 1), FALSE);
+
+ for (k = 0; k < delta; ++k)
+ set_cell_(vm, to+k, get_cell_(vm, from+k));
+ set_rI_(vm, 1, to+delta);
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+lda_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ gint r = 0;
+ mix_word_t val;
+ mix_ins_id_t id = mix_ins_id_from_ins(*ins);
+
+ g_assert(id >= mix_LDA && id <= mix_LDXN);
+
+ val = get_V_(vm, ins);
+ if ( id > mix_LDX && mix_fspec_left(ins->fspec) == 0)
+ mix_word_reverse_sign(val);
+ if ( (id > mix_LDA && id < mix_LDX) || (id > mix_LDAN && id < mix_LDXN) )
+ /* Bytes 1-3 of I regs are always null */
+ val = mix_word_set_field(mix_fspec_new(1,3),MIX_WORD_ZERO,val);
+
+ switch (id) {
+ case mix_LDA: case mix_LDAN: r = A_; break;
+ case mix_LDX: case mix_LDXN: r = X_; break;
+ case mix_LD1: case mix_LD1N: r = I1_; break;
+ case mix_LD2: case mix_LD2N: r = I2_; break;
+ case mix_LD3: case mix_LD3N: r = I3_; break;
+ case mix_LD4: case mix_LD4N: r = I4_; break;
+ case mix_LD5: case mix_LD5N: r = I5_; break;
+ case mix_LD6: case mix_LD6N: r = I6_; break;
+ default: g_assert_not_reached();
+ }
+ set_reg_(vm, r, val);
+ inc_loc_(vm);
+ return TRUE;
+}
+
+
+static gboolean
+sta_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_address_t addr = get_M_(vm, ins);
+ mix_ins_id_t id = mix_ins_id_from_ins(*ins);
+ mix_word_t from;
+
+ g_assert(id >= mix_STA && id <= mix_STZ);
+ switch (id) {
+ case mix_STA: from = get_rA_(vm); break;
+ case mix_STX: from = get_rX_(vm); break;
+ case mix_STJ: from = get_rJ_(vm); break;
+ case mix_STZ: from = MIX_WORD_ZERO; break;
+ default: from = get_rI_(vm, id - mix_ST1 + 1); break;
+ }
+ set_cell_(vm, addr,
+ mix_word_store_field(ins->fspec, from, get_cell_(vm, addr)));
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+jbs_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert (ins->opcode == mix_opJBUS);
+ g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
+ g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE);
+ if ( mix_device_busy (get_dev_ (vm, ins->fspec)) ) {
+ set_rJ_(vm, get_loc_ (vm));
+ set_loc_ (vm, get_M_ (vm, ins));
+ } else inc_loc_ (vm);
+ return TRUE;
+}
+
+static gboolean
+ioc_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_address_t addr;
+ mix_device_t *dev;
+ gboolean result;
+
+ g_assert(ins->opcode == mix_opIOC);
+ addr = get_M_ (vm, ins);
+ g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
+ dev = get_dev_ (vm, ins->fspec);
+ g_return_val_if_fail (dev != NULL, TRUE);
+ result =
+ mix_device_ioc (dev, addr);
+
+ inc_loc_(vm);
+ return result;
+}
+
+static gboolean
+inp_handler_ (mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_address_t addr;
+ mix_device_t *dev;
+ gboolean result;
+
+ g_assert(ins->opcode == mix_opIN);
+ addr = get_M_ (vm, ins);
+ g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
+ g_return_val_if_fail (MEMOK_(addr), TRUE);
+ dev = get_dev_ (vm, ins->fspec);
+ g_return_val_if_fail ( dev != NULL, TRUE);
+ g_return_val_if_fail (MEM_CELLS_NO_ - addr > mix_device_block_size(dev),
+ TRUE);
+ result =
+ mix_device_read (dev, get_cell_ptr_ (vm, addr));
+
+ inc_loc_(vm);
+ return result;
+}
+
+static gboolean
+out_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_address_t addr;
+ mix_device_t *dev;
+ gboolean result;
+
+ g_assert(ins->opcode == mix_opOUT);
+ addr = get_M_ (vm, ins);
+ g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
+ g_return_val_if_fail (MEMOK_(addr), TRUE);
+ dev = get_dev_ (vm, ins->fspec);
+ g_return_val_if_fail ( dev != NULL, TRUE);
+ g_return_val_if_fail (MEM_CELLS_NO_ - addr > mix_device_block_size(dev),
+ TRUE);
+ result =
+ mix_device_write (dev, get_cell_ptr_ (vm, addr));
+
+ inc_loc_(vm);
+ return result;
+}
+
+static gboolean
+jrd_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert(ins->opcode == mix_opJRED);
+ g_return_val_if_fail (ins->fspec < BD_NO_, TRUE);
+ g_return_val_if_fail (get_dev_ (vm, ins->fspec) != NULL, TRUE);
+ inc_loc_ (vm);
+ if ( !mix_device_busy (get_dev_ (vm, ins->fspec)) )
+ {
+ set_rJ_(vm, get_loc_(vm));
+ set_loc_ (vm, get_M_ (vm, ins));
+ }
+ return TRUE;
+}
+
+static gboolean
+jmp_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ gboolean jump = FALSE;
+ mix_address_t addr = get_M_(vm, ins);
+ mix_ins_id_t id = mix_ins_id_from_ins(*ins);
+
+ g_assert(ins->opcode == mix_opJMP);
+ g_return_val_if_fail(MEMOK_(addr), FALSE);
+ switch ( id ) {
+ case mix_JMP:
+ case mix_JSJ:
+ jump = TRUE;
+ break;
+ case mix_JOV:
+ jump = get_over_(vm);
+ if (jump) set_over_(vm, FALSE);
+ break;
+ case mix_JNOV:
+ jump = !get_over_(vm);
+ set_over_(vm, FALSE);
+ break;
+ case mix_JL:
+ jump = ( get_cmp_(vm) == mix_LESS );
+ break;
+ case mix_JE:
+ jump = ( get_cmp_(vm) == mix_EQ );
+ break;
+ case mix_JG:
+ jump = ( get_cmp_(vm) == mix_GREAT );
+ break;
+ case mix_JGE:
+ jump = ( get_cmp_(vm) != mix_LESS );
+ break;
+ case mix_JNE:
+ jump = ( get_cmp_(vm) != mix_EQ );
+ break;
+ case mix_JLE:
+ jump = ( get_cmp_(vm) != mix_GREAT );
+ break;
+ default:
+ return FALSE;
+ }
+
+ inc_loc_(vm);
+ if ( jump ) {
+ if ( id != mix_JSJ ) set_rJ_(vm, get_loc_(vm));
+ set_loc_(vm, addr);
+ }
+ return TRUE;
+}
+
+static gboolean
+jpx_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ gboolean jump = FALSE;
+ mix_address_t addr = get_M_(vm, ins);
+ mix_ins_id_t id = mix_ins_id_from_ins(*ins);
+ mix_word_t val;
+
+ g_assert(ins->opcode >= mix_opJAx || ins->opcode <= mix_opJXx);
+ g_return_val_if_fail(MEMOK_(addr), FALSE);
+
+ switch (ins->opcode) {
+ case mix_opJAx: val = get_rA_(vm); break;
+ case mix_opJXx: val = get_rX_(vm); break;
+ default: val = get_rI_(vm, ins->opcode - mix_opJAx);
+ }
+
+ switch (id) {
+ case mix_JAN: case mix_JXN:
+ case mix_J1N: case mix_J2N: case mix_J3N:
+ case mix_J4N: case mix_J5N: case mix_J6N:
+ jump = mix_word_is_negative(val) && val != MIX_WORD_MINUS_ZERO;
+ break;
+ case mix_JAZ: case mix_JXZ:
+ case mix_J1Z: case mix_J2Z: case mix_J3Z:
+ case mix_J4Z: case mix_J5Z: case mix_J6Z:
+ jump = mix_word_magnitude(val) == MIX_WORD_ZERO;
+ break;
+ case mix_JAP: case mix_JXP:
+ case mix_J1P: case mix_J2P: case mix_J3P:
+ case mix_J4P: case mix_J5P: case mix_J6P:
+ jump = mix_word_is_positive(val) && val != MIX_WORD_ZERO;
+ break;
+ case mix_JANN: case mix_JXNN:
+ case mix_J1NN: case mix_J2NN: case mix_J3NN:
+ case mix_J4NN: case mix_J5NN: case mix_J6NN:
+ jump = mix_word_magnitude(val) == MIX_WORD_ZERO
+ || mix_word_is_positive(val);
+ break;
+ case mix_JANZ: case mix_JXNZ:
+ case mix_J1NZ: case mix_J2NZ: case mix_J3NZ:
+ case mix_J4NZ: case mix_J5NZ: case mix_J6NZ:
+ jump = mix_word_magnitude(val) != MIX_WORD_ZERO;
+ break;
+ case mix_JANP: case mix_JXNP:
+ case mix_J1NP: case mix_J2NP: case mix_J3NP:
+ case mix_J4NP: case mix_J5NP: case mix_J6NP:
+ jump = mix_word_magnitude(val) == MIX_WORD_ZERO
+ || mix_word_is_negative(val);
+ break;
+ default:
+ return FALSE;
+ }
+
+ inc_loc_(vm);
+ if ( jump ) {
+ set_rJ_(vm, get_loc_(vm));
+ set_loc_(vm, addr);
+ }
+ return TRUE;
+}
+
+static gboolean
+ina_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ mix_word_t val = mix_short_to_word_fast(get_M_(vm, ins));
+ mix_ins_id_t id = mix_ins_id_from_ins(*ins);
+ gint r;
+
+ g_assert(id >= mix_INCA && id <= mix_ENNX);
+
+ switch (ins->opcode) {
+ case mix_opINCA: r = A_; break;
+ case mix_opINCX: r = X_; break;
+ default: r = I1_ + ins->opcode - mix_opINC1;
+ }
+
+ switch (id) {
+ case mix_ENTA: case mix_ENTX:
+ break;
+ case mix_ENT1: case mix_ENT2: case mix_ENT3:
+ case mix_ENT4: case mix_ENT5: case mix_ENT6:
+ val = mix_word_set_field(mix_fspec_new(1,3), MIX_WORD_ZERO, val);
+ break;
+ case mix_INCA: case mix_INCX:
+ if ( mix_word_add_and_carry(val, get_reg_(vm, r), NULL, &val) )
+ set_over_(vm, TRUE);
+ break;
+ case mix_INC1: case mix_INC2: case mix_INC3:
+ case mix_INC4: case mix_INC5: case mix_INC6:
+ mix_word_add_and_carry(val, get_reg_(vm,r), NULL, &val);
+ val = mix_word_set_field(mix_fspec_new(1,3), MIX_WORD_ZERO, val);
+ break;
+ case mix_DECA: case mix_DECX:
+ if ( mix_word_add_and_carry(mix_word_negative(val), get_reg_(vm, r),
+ NULL, &val) )
+ set_over_(vm, TRUE);
+ break;
+ case mix_DEC1: case mix_DEC2: case mix_DEC3:
+ case mix_DEC4: case mix_DEC5: case mix_DEC6:
+ mix_word_add_and_carry(mix_word_negative(val), get_reg_(vm,r), NULL, &val);
+ val = mix_word_set_field(mix_fspec_new(1,3), MIX_WORD_ZERO, val);
+ break;
+ case mix_ENN1: case mix_ENN2: case mix_ENN3:
+ case mix_ENN4: case mix_ENN5: case mix_ENN6:
+ val = mix_word_set_field(mix_fspec_new(1,3), MIX_WORD_ZERO, val);
+ /* fallthrough */
+ case mix_ENNA: case mix_ENNX:
+ mix_word_reverse_sign(val);
+ break;
+ default:
+ return FALSE;
+ }
+ set_reg_(vm, r, val);
+ inc_loc_(vm);
+ return TRUE;
+}
+
+static gboolean
+cmp_handler_(mix_vm_t *vm, const mix_ins_t *ins)
+{
+ g_assert(ins->opcode >= mix_opCMPA && ins->opcode <= mix_opCMPX);
+
+ if ( ins->fspec == 0 ) { /* shortcut: +0 == -0 */
+ set_cmp_(vm, mix_EQ);
+ } else {
+ mix_word_t v = get_V_(vm, ins);
+ mix_word_t reg;
+ mix_cmpflag_t flag;
+
+ switch (ins->opcode) {
+ case mix_opCMPA:
+ reg = get_rA_(vm);
+ break;
+ case mix_opCMPX:
+ reg = get_rX_(vm);
+ break;
+ default:
+ reg = get_rI_(vm, ins->opcode - mix_opCMPA);
+ break;
+ }
+ reg = mix_word_get_field(ins->fspec, reg);
+ mix_word_add_and_carry(reg, mix_word_negative(v), NULL, &reg);
+ if ( mix_word_magnitude(reg) == MIX_WORD_ZERO ) flag = mix_EQ;
+ else if ( mix_word_is_positive(reg) ) flag = mix_GREAT;
+ else flag = mix_LESS;
+ set_cmp_(vm, flag);
+ }
+ inc_loc_(vm);
+ return TRUE;
+}
+
+ins_handler_t_ ins_handlers_[MIX_BYTE_MAX + 1] = {
+ nop_handler_, add_handler_, add_handler_, mul_handler_, div_handler_,
+ spc_handler_, sla_handler_, mov_handler_, lda_handler_, lda_handler_,
+ lda_handler_, lda_handler_, lda_handler_, lda_handler_, lda_handler_,
+ lda_handler_, lda_handler_, lda_handler_, lda_handler_, lda_handler_,
+ lda_handler_, lda_handler_, lda_handler_, lda_handler_, sta_handler_,
+ sta_handler_, sta_handler_, sta_handler_, sta_handler_, sta_handler_,
+ sta_handler_, sta_handler_, sta_handler_, sta_handler_, jbs_handler_,
+ ioc_handler_, inp_handler_, out_handler_, jrd_handler_, jmp_handler_,
+ jpx_handler_, jpx_handler_, jpx_handler_, jpx_handler_, jpx_handler_,
+ jpx_handler_, jpx_handler_, jpx_handler_, ina_handler_, ina_handler_,
+ ina_handler_, ina_handler_, ina_handler_, ina_handler_, ina_handler_,
+ ina_handler_, cmp_handler_, cmp_handler_, cmp_handler_, cmp_handler_,
+ cmp_handler_, cmp_handler_, cmp_handler_, cmp_handler_,
+};
diff --git a/mixlib/xmix_vm.h b/mixlib/xmix_vm.h
new file mode 100644
index 0000000..cfbf65a
--- /dev/null
+++ b/mixlib/xmix_vm.h
@@ -0,0 +1,117 @@
+/* ---------------------- xmix_vm.h :
+ * This file contains internal declarations used in the implementation
+ * of the mix_vm_t type.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef XMIX_VM_H
+#define XMIX_VM_H
+
+#include "mix_symbol_table.h"
+#include "mix_device.h"
+#include "mix_src_file.h"
+#include "mix_vm.h"
+
+/* The mix_vm_t type */
+enum {IREG_NO_ = 6, BD_NO_ = 21, MEM_CELLS_NO_ = MIX_VM_CELL_NO};
+struct mix_vm_t
+{
+ mix_word_t reg[IREG_NO_+3];
+ mix_word_t cell[MEM_CELLS_NO_];
+ gboolean overflow;
+ mix_cmpflag_t cmpflag;
+ mix_short_t loc_count;
+ gboolean is_halted;
+ mix_device_t * devices[BD_NO_];
+ mix_address_t start_addr; /* start address of loaded file */
+ GTree *line_table; /* source line no -> address */
+ GTree *address_table; /* adress -> source line no */
+ gint8 bp[MEM_CELLS_NO_/8]; /* each bit signals a break point */
+ mix_vm_clock_t *clock; /* the vm clock */
+ mix_symbol_table_t *symbol_table;
+ mix_src_file_t *src_file; /* source of last loaded code file */
+};
+
+/* Macros for accessing/modifying the above structure.
+ * Warning: the arguments of these macros must not have side-effects.
+ */
+#define IOK_(idx) ( (idx) > 0 && (idx) < IREG_NO_+1 )
+#define MEMOK_(addr) ( mix_short_is_positive(addr) && (addr) < MEM_CELLS_NO_ )
+#define REGOK_(r) ( (r) >= 0 && (r) < IREG_NO_ + 3 )
+
+enum { A_ = 0, X_, J_, I1_, I2_, I3_, I4_, I5_, I6_ };
+
+#define get_reg_(vm, r) ((vm)->reg[r])
+#define get_rA_(vm) get_reg_(vm, A_)
+#define get_rX_(vm) get_reg_(vm, X_)
+#define get_rJ_(vm) get_reg_(vm, J_)
+#define get_rI_(vm,idx) get_reg_(vm, I1_ + (idx) - 1)
+#define get_cell_(vm,addr) ( MEMOK_(addr) ? vm->cell[addr] : MIX_WORD_ZERO )
+#define get_cell_ptr_(vm,addr) ( MEMOK_(addr) ? (vm->cell) + addr : NULL )
+#define get_cmp_(vm) (vm->cmpflag)
+#define get_over_(vm) (vm->overflow)
+#define get_loc_(vm) (vm->loc_count)
+#define get_clock_(vm) (vm->clock)
+
+#define set_reg_(vm,r,x) \
+do { \
+ if ( REGOK_(r) ) vm->reg[r] = (x); \
+} while (FALSE)
+
+#define set_rA_(vm,x) set_reg_(vm,A_,x)
+#define set_rX_(vm,x) set_reg_(vm,X_,x)
+#define set_rJ_(vm,x) set_reg_(vm,J_,(x)&MIX_SHORT_MAX)
+#define set_rI_(vm,idx,x) set_reg_(vm,(idx) + I1_ - 1,x)
+
+#define set_cell_(vm,addr,x) \
+do { \
+ if ( MEMOK_(addr) ) (vm)->cell[addr] = (x); \
+} while (FALSE)
+
+#define set_cmp_(vm,x) (vm)->cmpflag = (x)
+#define set_over_(vm,x) (vm)->overflow = (x)
+#define set_loc_(vm,x) (vm)->loc_count = (x)&MIX_SHORT_MAX
+
+#define inc_loc_(vm) \
+do { \
+ vm->loc_count++; \
+ vm->loc_count &= MIX_SHORT_MAX; \
+} while(FALSE)
+
+#define is_halted_(vm) ((vm)->is_halted)
+#define halt_(vm,val) ((vm)->is_halted = (val))
+#define set_start_(vm,val) ((vm)->start_addr = (val))
+#define reset_loc_(vm) set_loc_ (vm, vm->start_addr)
+#define update_time_(vm,ins) mix_vm_clock_add_lapse (get_clock_(vm), ins)
+
+/* Breakpoints handling */
+#define bp_clear_all_(vm) memset (vm->bp, 0, MEM_CELLS_NO_/8)
+#define bp_set_(vm,addr) vm->bp[(addr)>>3] |= 1 << ((addr)&7)
+#define bp_clear_(vm,addr) vm->bp[(addr)>>3] &= ~(1 << ((addr)&7))
+#define bp_is_set_(vm,addr) vm->bp[(addr)>>3] & (1 << ((addr)&7))
+
+/* Instruction handlers */
+typedef gboolean (*ins_handler_t_)(mix_vm_t *,const mix_ins_t *);
+
+extern ins_handler_t_ ins_handlers_[MIX_BYTE_MAX + 1];
+
+
+#endif /* XMIX_VM_H */
+
diff --git a/mixutils/.cvsignore b/mixutils/.cvsignore
new file mode 100644
index 0000000..349354d
--- /dev/null
+++ b/mixutils/.cvsignore
@@ -0,0 +1,6 @@
+.deps
+Makefile
+Makefile.in
+mixasm
+mixcmp
+mixvm
diff --git a/mixutils/Makefile.am b/mixutils/Makefile.am
new file mode 100644
index 0000000..2bd03be
--- /dev/null
+++ b/mixutils/Makefile.am
@@ -0,0 +1,18 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2000 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+INCLUDES = -I$(includedir)
+LDADD = $(top_builddir)/mixlib/libmix.a
+
+bin_PROGRAMS = mixasm mixvm
+mixasm_SOURCES = mixasm.c mixasm_comp.h mixasm_comp.c
+mixvm_SOURCES = mixvm.c mixvm_loop.c mixvm_command.h mixvm_command.c
diff --git a/mixutils/mixasm.c b/mixutils/mixasm.c
new file mode 100644
index 0000000..64f0f3d
--- /dev/null
+++ b/mixutils/mixasm.c
@@ -0,0 +1,126 @@
+/* -*-c-*- -------------- mixasm.c:
+ * Main function of mixasm, the mix assembler
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <mixlib/mix.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+
+#include "mixasm_comp.h"
+
+enum {
+ VER_OPT = 'v',
+ HELP_OPT = 'h',
+ USAGE_OPT = 'u',
+ OUT_OPT = 'o',
+ LIST_OPT = 'l',
+ DEBUG_OPT = 'g'
+};
+
+
+static struct option long_options_[] =
+{
+ {"version", no_argument, 0, VER_OPT},
+ {"help", no_argument, 0, HELP_OPT},
+ {"usage", no_argument, 0, USAGE_OPT},
+ {"output", required_argument, 0, OUT_OPT},
+ {"list", optional_argument, 0, VER_OPT},
+ {"debug", no_argument, 0, DEBUG_OPT},
+ {0, 0, 0, 0}
+};
+
+static const gchar *USAGE_ =
+N_("Usage: %s [-vhulg] [-o OUTPUT_FILE] [--version] [--help]\n"
+ "\t[--usage] [--debug] [--output=OUTPUT_FILE] [--list[=LIST_FILE]] file\n");
+
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ const char *prog_name = argv[0];
+ const char *src = NULL, *out = NULL, *list = NULL;
+ gboolean use_list = FALSE, debug = FALSE;
+
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ while (1)
+ {
+ c = getopt_long (argc, argv, "vhuo:lg", long_options_, (int*)0);
+
+ /* Detect the end of the options. */
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case HELP_OPT: case USAGE_OPT:
+ fprintf (stderr, _(USAGE_), prog_name);
+ return EXIT_SUCCESS;
+ case VER_OPT:
+ fprintf (stderr, _("%s %s, MIX compiler.\n"), prog_name, VERSION);
+ fprintf (stderr, MIX_GPL_LICENSE);
+ return EXIT_SUCCESS;
+ case OUT_OPT:
+ out = optarg;
+ break;
+ case LIST_OPT:
+ use_list = TRUE;
+ list = optarg;
+ break;
+ case DEBUG_OPT:
+ debug = TRUE;
+ break;
+ case '?':
+ /* getopt already handles the output of a warning message */
+ fprintf (stderr, _("(Try: %s -h)\n"), prog_name);
+ return EXIT_FAILURE;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ if ( optind == argc )
+ {
+ fprintf (stderr, _("*** Error: Missing source file.\n"));
+ return EXIT_FAILURE;
+ }
+ if ( optind < argc-1 )
+ {
+ fprintf (stderr, _("*** Error: Too many input files.\n"));
+ return EXIT_FAILURE;
+ }
+ src = argv[optind];
+
+
+ mix_init_lib ();
+
+ c = mix_asm_compile (src, out, use_list, list, debug);
+
+ mix_release_lib ();
+
+ return c;
+
+}
+
diff --git a/mixutils/mixasm_comp.c b/mixutils/mixasm_comp.c
new file mode 100644
index 0000000..87b38be
--- /dev/null
+++ b/mixutils/mixasm_comp.c
@@ -0,0 +1,72 @@
+/* -*-c-*- -------------- mixasm_comp.c :
+ * Implementation of the functions declared in mixasm_comp.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <mixlib/mix.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <mixlib/mix_parser.h>
+#include "mixasm_comp.h"
+
+int
+mix_asm_compile(const gchar *src, const gchar *out, gboolean use_list,
+ const gchar *list, gboolean debug)
+{
+ int result = EXIT_SUCCESS;
+ mix_parser_t *parser;
+ mix_parser_err_t error;
+
+ if ( (parser = mix_parser_new(src)) == NULL )
+ {
+ fprintf(stderr, _("*** Unable to open source file %s\n"), src);
+ return EXIT_FAILURE;
+ }
+ if ( mix_parser_compile(parser) == MIX_PERR_OK )
+ {
+ guint k;
+ if ( ( k = mix_parser_warning_count(parser) ) != 0 )
+ fprintf(stderr, _("(%d warning(s))\n"), k);
+ if ( (error = mix_parser_write_code(parser, out, debug)) != MIX_PERR_OK )
+ {
+ fprintf(stderr, _("*** Error writing output code file: %s\n"),
+ mix_parser_err_string(error));
+ result = EXIT_FAILURE;
+ }
+ else if ( use_list
+ && (error = mix_parser_write_listing(parser, list)) !=
+ MIX_PERR_OK)
+ {
+ fprintf(stderr, _("*** Error writing listing file: %s\n"),
+ mix_parser_err_string(error));
+ result = EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ fprintf(stderr, _("(%d warning(s), %d error(s))\n"),
+ mix_parser_warning_count(parser), mix_parser_err_count(parser));
+ result = EXIT_FAILURE;
+ }
+
+ mix_parser_delete(parser);
+ return result;
+}
+
+
diff --git a/mixutils/mixasm_comp.h b/mixutils/mixasm_comp.h
new file mode 100644
index 0000000..0fef0dd
--- /dev/null
+++ b/mixutils/mixasm_comp.h
@@ -0,0 +1,35 @@
+/* -*-c-*- ---------------- mixasm_comp.h :
+ * Declarations of functions used to compile mix source files.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXASM_COMP_H
+#define MIXASM_COMP_H
+
+#include <glib.h>
+
+extern int
+mix_asm_compile(const gchar *src, const gchar *out, gboolean use_list,
+ const gchar *list, gboolean debug);
+
+
+
+#endif /* MIXASM_COMP_H */
+
diff --git a/mixutils/mixvm.c b/mixutils/mixvm.c
new file mode 100644
index 0000000..eafc8a0
--- /dev/null
+++ b/mixutils/mixvm.c
@@ -0,0 +1,155 @@
+/* -*-c-*- -------------- mixvm.c :
+ * Main function for mixvm, the mix vm simulator
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+
+#include <mixlib/mix.h>
+#include <mixlib/mix_vm.h>
+#include <mixlib/mix_vm_dump.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+
+extern void
+mix_vmloop (const gchar *code_file, gboolean use_emacs);
+
+static void
+mix_vmrun (const gchar *code_file, gboolean dump);
+
+enum {
+ VER_OPT = 'v',
+ HELP_OPT = 'h',
+ USAGE_OPT = 'u',
+ RUN_OPT = 'r',
+ DUMP_OPT = 'd',
+ EMACS_OPT = 'e', /* used by mixvm-gud only */
+};
+
+static const char *options_ = "vhurd"; /* no short opt for --emacs */
+
+static struct option long_options_[] =
+{
+ {"version", no_argument, 0, VER_OPT},
+ {"help", no_argument, 0, HELP_OPT},
+ {"usage", no_argument, 0, USAGE_OPT},
+ {"run", required_argument, 0, RUN_OPT},
+ {"dump", no_argument, 0, DUMP_OPT},
+ /* pek: yo! */
+ {"emacs", no_argument, 0, EMACS_OPT},
+ {0, 0, 0, 0}
+};
+
+static const gchar *USAGE_ =
+N_("Usage: %s [-vhurd] [--version] [--help] [--usage] [--run] [--dump] [MIX_FILE]\n");
+
+int
+main (int argc, char **argv)
+{
+ int c;
+ const char *prog_name = argv[0];
+ const char *in = NULL;
+ gboolean run = FALSE;
+ gboolean dump = FALSE;
+ gboolean emacs = FALSE;
+
+ setlocale (LC_ALL, "");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+
+ while (1)
+ {
+ c = getopt_long (argc, argv, options_, long_options_, (int*)0);
+
+ /* Detect the end of the options. */
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case HELP_OPT: case USAGE_OPT:
+ fprintf (stderr, _(USAGE_), prog_name);
+ return EXIT_SUCCESS;
+ case VER_OPT:
+ fprintf (stderr, _("%s %s, MIX Virtual Machine.\n"),
+ prog_name, VERSION);
+ fprintf (stderr, MIX_GPL_LICENSE);
+ return EXIT_SUCCESS;
+ case RUN_OPT:
+ in = optarg;
+ run = TRUE;
+ break;
+ case DUMP_OPT:
+ dump = TRUE;
+ break;
+ case '?':
+ /* getopt already handles the output of a warning message */
+ fprintf (stderr, _("(Try: %s -h)\n"), prog_name);
+ return EXIT_FAILURE;
+ case EMACS_OPT:
+ emacs = TRUE;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ }
+
+ if ( optind < argc-1 )
+ {
+ fprintf (stderr, _("*** Error: Too many input files.\n"));
+ return EXIT_FAILURE;
+ }
+
+ if (!in) in = argv[optind];
+
+ mix_init_lib ();
+
+ if (run) mix_vmrun(in, dump);
+ else mix_vmloop (in, emacs);
+
+ mix_release_lib ();
+
+ return EXIT_SUCCESS;
+
+}
+
+
+static void
+mix_vmrun (const gchar *code_file, gboolean dump)
+{
+ mix_vm_t *vm = mix_vm_new ();
+ if (!mix_vm_load_file (vm, code_file)) {
+ fprintf (stderr, _("Error loading %s file\n"), code_file);
+ return;
+ }
+ mix_vm_run (vm);
+ printf (_("** Execution time: %ld\n"), mix_vm_get_uptime (vm));
+ if (dump) {
+ mix_dump_context_t *dc = mix_dump_context_new (MIX_DUMP_DEF_CHANNEL,
+ 0, 0,
+ MIX_DUMP_ALL_NOMEM);
+ mix_vm_dump (vm, dc);
+ mix_dump_context_delete (dc);
+ }
+ mix_vm_delete (vm);
+}
+
+
diff --git a/mixutils/mixvm_command.c b/mixutils/mixvm_command.c
new file mode 100644
index 0000000..e1c03bf
--- /dev/null
+++ b/mixutils/mixvm_command.c
@@ -0,0 +1,367 @@
+/* -*-c-*- -------------- mixvm_command.c :
+ * Implementation of the functions declared in mixvm_command.h
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <mixlib/mix.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <mixlib/mix.h>
+
+#ifdef HAVE_LIBREADLINE
+# include <readline/readline.h>
+# include <readline/history.h>
+#else
+ typedef int Function ();
+#endif /* HAVE_LIBREADLINE */
+
+#include <mixlib/mix_vm.h>
+#include <mixlib/mix_vm_dump.h>
+#include <mixlib/mix_eval.h>
+#include <mixlib/mix_src_file.h>
+#include <mixlib/mix_vm_command.h>
+#include "mixvm_command.h"
+
+/* The names of functions that actually do the manipulation. */
+#define DEC_FUN(name) \
+static int cmd_##name (char *arg)
+
+DEC_FUN (help_);
+DEC_FUN (shell_);
+DEC_FUN (compile_);
+DEC_FUN (edit_);
+DEC_FUN (quit_);
+
+/* A structure which contains information on the commands this program
+ can understand. */
+typedef struct {
+ const char *name; /* User printable name of the function. */
+ Function *func; /* Function to call to do the job. */
+ const char *doc; /* Documentation for this function. */
+ const char *usage; /* Usage */
+} COMMAND;
+
+COMMAND commands[] = {
+ { "help", cmd_help_, N_("Display this text"), "help [COMMAND]" },
+ { "shell", cmd_shell_, N_("Execute shell command"), "shell COMMAND" },
+ { "compile", cmd_compile_, N_("Compile a source file"), "compile FILENAME"},
+ { "edit", cmd_edit_, N_("Edit a source file"), "edit FILENAME"},
+ { "quit", cmd_quit_, N_("Quit the program"), "quit" },
+ { (char *)NULL, (Function *)NULL, (char *)NULL }
+};
+
+#define LOCAL_COMANDS_NO_ ((sizeof (commands) / sizeof (commands[0])) - 1)
+#define MIX_COMMANDS_NO_ MIX_CMD_INVALID+1
+#define ALL_COMMANDS_NO_ LOCAL_COMANDS_NO_+MIX_COMMANDS_NO_
+
+static const char *mix_commands_[ALL_COMMANDS_NO_] = {NULL};
+
+
+
+#ifdef HAVE_LIBREADLINE
+/* readline functions */
+static char *
+mixvm_cmd_generator_ (char *text, int state);
+
+
+/* Attempt to complete on the contents of TEXT. START and END bound the
+ region of rl_line_buffer that contains the word to complete. TEXT is
+ the word to complete. We can use the entire contents of rl_line_buffer
+ in case we want to do some simple parsing. Return the array of matches,
+ or NULL if there aren't any. */
+static char **
+mixvm_cmd_completion_ (char *text, int start, int end)
+{
+ char **matches;
+
+ matches = (char **)NULL;
+
+ /* If this word is at the start of the line, then it is a command
+ to complete. Otherwise it is the name of a file in the current
+ directory. */
+ if (start == 0)
+ matches = completion_matches (text, mixvm_cmd_generator_);
+
+ return (matches);
+}
+
+/* Generator function for command completion. STATE lets us know whether
+ to start from scratch; without any state (i.e. STATE == 0), then we
+ start at the top of the list. */
+static char *
+mixvm_cmd_generator_ (char *text, int state)
+{
+ static int list_index, len;
+ const char *name;
+
+ /* If this is a new word to complete, initialize now. This includes
+ saving the length of TEXT for efficiency, and initializing the index
+ variable to 0. */
+ if (!state)
+ {
+ list_index = 0;
+ len = strlen (text);
+ }
+
+ /* Return the next name which partially matches from the command list. */
+ while ((name = mix_commands_[list_index]) != NULL)
+ {
+ list_index++;
+ if (strncmp (name, text, len) == 0)
+ return (g_strdup (name));
+ }
+
+ /* If no names matched, then return NULL. */
+ return ((char *)NULL);
+}
+#endif /* HAVE_LIBREADLINE */
+
+/* command functions */
+static COMMAND *
+find_command_ (const char *name)
+{
+ int i;
+
+ for (i = 0; commands[i].name; i++)
+ if (strcmp (name, commands[i].name) == 0)
+ return (&commands[i]);
+
+ return ((COMMAND *)NULL);
+}
+
+
+/* mixvm dispatcher */
+static mix_vm_cmd_dispatcher_t *dis_ = NULL;
+
+/* emacs interface */
+static void
+emacs_output_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg, gpointer data)
+{
+ /* pek: probably bad that we snag the src w/every emacs_output_,
+ however when multiple files are supported then this will
+ have to be done each time (but the info will be snagged
+ from elsewhere...) */
+ const mix_vm_t *vm = mix_vm_cmd_dispatcher_get_vm (dis);
+ const mix_src_file_t *src = mix_vm_get_src_file (vm);
+ const gchar *path = mix_src_file_get_path (src);
+
+ mix_address_t loc = mix_vm_get_prog_count (vm);
+ guint lineno = mix_vm_get_address_lineno (vm, loc);
+
+ printf ("\032\032mixvm:%s%s:%d\n", path, MIX_SRC_DEFEXT, lineno);
+ return;
+}
+
+static int
+cmd_help_ (char *arg)
+{
+ int i;
+ int printed = 0;
+
+ for (i = 0; commands[i].name; i++)
+ {
+ if (!*arg || (strcmp (arg, commands[i].name) == 0))
+ {
+ printf (_("%s\t\t%s. Usage: %s\n"), commands[i].name,
+ _(commands[i].doc), commands[i].usage);
+ printed++;
+ }
+ }
+
+ if (printed > 1) printf ("\n");
+
+ for (i = LOCAL_COMANDS_NO_ + 1 /* skip help cmd */; mix_commands_[i]; i++)
+ {
+ if (!*arg || (strcmp (arg, mix_commands_[i]) == 0))
+ {
+ printf (_("%s\t\t%s. Usage: %s\n"), mix_commands_[i],
+ mix_vm_command_help (i - LOCAL_COMANDS_NO_),
+ mix_vm_command_usage (i - LOCAL_COMANDS_NO_));
+ printed++;
+ }
+ }
+
+ if (!printed) printf ("Command \'%s\' not found\n", arg);
+
+ return TRUE;
+
+}
+
+static int
+cmd_quit_ (char *arg)
+{
+ puts ("Quitting ...");
+ if ( dis_ ) mix_vm_cmd_dispatcher_delete (dis_);
+
+ /* pek: anything needed here to make the marker disappear??? */
+ return FALSE;
+}
+
+
+static int
+cmd_shell_ (char *arg)
+{
+ system (arg);
+ return TRUE;
+}
+
+static int
+cmd_compile_ (char *arg)
+{
+ gchar *line;
+
+ if ( strlen (arg) == 0 )
+ return cmd_help_ ("compile");
+
+ line = g_strconcat ("mixasm -g ", arg, NULL);
+ if ( system (line) == EXIT_SUCCESS )
+ fputs (_("Successful compilation\n"), stderr);
+ g_free (line);
+
+ return TRUE;
+}
+
+static int
+cmd_edit_ (char *arg)
+{
+ static const gchar * envars[] = { "MDK_EDITOR", "X_EDITOR", "EDITOR",
+ "VISUAL" };
+
+ static const guint s = sizeof (envars) / sizeof (envars[0]);
+ static const gchar *editor = NULL;
+
+ if ( strlen (arg) == 0 )
+ return cmd_help_ ("edit");
+
+ if (!editor)
+ {
+ int k;
+ for (k = 0; k < s; k++)
+ if ( (editor = getenv (envars[k])) != NULL ) break;
+ }
+ if (!editor)
+ {
+ int k;
+ fputs (_("Cannot find editor ("), stderr);
+ for (k = 0; k < s; k++)
+ fprintf (stderr, "%s ", envars[k]);
+ fputs (_("undefined)\n"), stderr);
+ }
+ else
+ {
+ gchar *line = g_strconcat (editor, " ", arg, NULL);
+ system (line);
+ g_free (line);
+ }
+
+ return TRUE;
+}
+
+
+
+/* external interface */
+void
+mixvm_cmd_init (char *arg, gboolean use_emacs)
+{
+ int k;
+ /* get local command names */
+ for (k = 0; k < LOCAL_COMANDS_NO_; ++k)
+ mix_commands_[k] = commands[k].name;
+ /* get external command names */
+ for (k = 0; k < MIX_CMD_INVALID; ++k)
+ mix_commands_[k + LOCAL_COMANDS_NO_] = mix_vm_command_to_string (k);
+ mix_commands_[ALL_COMMANDS_NO_ - 1] = NULL;
+
+#ifdef HAVE_LIBREADLINE
+ /* Tell the completer that we want a crack first. */
+ rl_attempted_completion_function = (CPPFunction *)mixvm_cmd_completion_;
+#endif /* HAVE_LIBREADLINE */
+
+ /* initialise the dispatcher */
+ dis_ = mix_vm_cmd_dispatcher_new (stdout, stderr);
+
+ if ( dis_ == NULL)
+ g_error (_("Failed initialisation (no memory resources)"));
+
+ /* install post hook for emacs interaction */
+ if (use_emacs)
+ {
+ mix_vm_cmd_dispatcher_post_hook (dis_, MIX_CMD_LOAD, emacs_output_, NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_, MIX_CMD_RUN, emacs_output_, NULL);
+ mix_vm_cmd_dispatcher_post_hook (dis_, MIX_CMD_NEXT, emacs_output_, NULL);
+ }
+
+ if (arg)
+ mix_vm_cmd_dispatcher_dispatch (dis_, MIX_CMD_LOAD, arg);
+}
+
+gboolean
+mixvm_cmd_exec (char *line)
+{
+ int i;
+ COMMAND *command;
+ char *cmd, *arg;
+ mix_vm_command_t mix_cmd;
+
+ if (!line) return cmd_quit_(NULL);
+
+ /* strip white space */
+ line = g_strstrip(line);
+
+ /* Isolate the command word. */
+ i = 0;
+ while (line[i] && isspace (line[i]))
+ i++;
+ cmd = line + i;
+
+ while (line[i] && !isspace (line[i]))
+ i++;
+
+ if (line[i])
+ line[i++] = '\0';
+
+ if (cmd == NULL || strlen (cmd) == 0)
+ return TRUE;
+
+ /* Get argument to command, if any. */
+ while (isspace (line[i]))
+ i++;
+
+ arg = line + i;
+
+ /* try to find local command */
+ command = find_command_ (cmd);
+ if (command)
+ return ((*(command->func)) (arg));
+
+ /* try to find mix command */
+ mix_cmd = mix_vm_command_from_string (cmd);
+
+ if (mix_cmd == MIX_CMD_INVALID)
+ fprintf (stderr, _("%s: No such command. Try \'help\'\n"), cmd);
+ else
+ mix_vm_cmd_dispatcher_dispatch (dis_, mix_cmd, arg);
+
+ return TRUE;
+}
+
+
diff --git a/mixutils/mixvm_command.h b/mixutils/mixvm_command.h
new file mode 100644
index 0000000..9741164
--- /dev/null
+++ b/mixutils/mixvm_command.h
@@ -0,0 +1,35 @@
+/* -*-c-*- ---------------- mixvm_command.h :
+ * Declarations for commands accepted by the mix virtual machine
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef MIXVM_COMMAND_H
+#define MIXVM_COMMAND_H
+
+#include <glib.h>
+
+extern void
+mixvm_cmd_init (char *arg, gboolean use_emacs);
+
+extern gboolean
+mixvm_cmd_exec (char *line);
+
+#endif /* MIXVM_COMMAND_H */
+
diff --git a/mixutils/mixvm_loop.c b/mixutils/mixvm_loop.c
new file mode 100644
index 0000000..a565832
--- /dev/null
+++ b/mixutils/mixvm_loop.c
@@ -0,0 +1,86 @@
+/* -*-c-*- -------------- mixvm_loop.c :
+ * Implementation of mix vm command loop.
+ * ------------------------------------------------------------------
+ * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#define _GNU_SOURCE 1
+#include <stdio.h>
+
+#include <mixlib/mix.h>
+#include "mixvm_command.h"
+
+#ifdef HAVE_LIBHISTORY
+# include <readline/history.h>
+#else
+# define add_history(x) ((void)0)
+#endif
+
+#ifdef HAVE_LIBREADLINE
+# include <readline/readline.h>
+#else /* !HAVE_LIBREADLINE */
+static char *
+readline (char *prompt)
+{
+ char *line = NULL;
+ size_t s = 0;
+
+ printf ("%s", prompt);
+ getline (&line, &s, stdin);
+ return line;
+}
+#endif /* HAVE_LIBREADLINE */
+
+/* A static variable for holding the line. */
+static char *line_read = (char *)NULL;
+static const char *PROMPT = N_("MIX > ");
+
+/* Read a string, and return a pointer to it. Returns NULL on EOF. */
+static char *
+rl_gets ()
+{
+ /* If the buffer has already been allocated, return the memory
+ to the free pool. */
+ if (line_read)
+ {
+ g_free (line_read);
+ line_read = (char *)NULL;
+ }
+
+ /* Get a line from the user. */
+ line_read = readline ((char *)PROMPT);
+
+ /* If the line has any text in it, save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+
+ return (line_read);
+}
+
+
+/* The main command loop of the virtual machine */
+void
+mix_vmloop (const gchar *file, gboolean use_emacs)
+{
+ mixvm_cmd_init ((char *)file, use_emacs);
+ while ( mixvm_cmd_exec (rl_gets ()) )
+ ;
+}
+
+
diff --git a/po/.cvsignore b/po/.cvsignore
new file mode 100644
index 0000000..c697044
--- /dev/null
+++ b/po/.cvsignore
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+POTFILES
+ca.gmo
+cat-id-tbl.c
+mdk.pot
+stamp-cat-id
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..7af10c3
--- /dev/null
+++ b/po/ChangeLog
@@ -0,0 +1,3 @@
+2000-02-08 jose antonio ortega ruiz <jaortega@retemail.es>
+
+ * ca.po: New file
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..8087956
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,10 @@
+# List of source files containing translatable strings.
+# Package source files
+mixutils/mixasm.c
+mixutils/mixasm_comp.c
+mixutils/mixvm.c
+mixutils/mixvm_command.c
+
+mixlib/mix_parser.c
+mixlib/mix_vm_dump.c
+
diff --git a/samples/.cvsignore b/samples/.cvsignore
new file mode 100644
index 0000000..ebb2d73
--- /dev/null
+++ b/samples/.cvsignore
@@ -0,0 +1,36 @@
+Makefile
+Makefile.in
+cardwr.dev
+disk0.dev
+disk1.dev
+disk2.dev
+disk3.dev
+disk4.dev
+disk5.dev
+disk6.dev
+disk7.dev
+hello.mix
+hello.mls
+paper.dev
+primes.mix
+primes.mls
+printer.dev
+stress1.mix
+stress2.mix
+stress2.mls
+stress3.mix
+stress3.mixal
+stress3.mls
+stress4.mix
+stress4.mls
+stress5.mix
+stress5.mixal
+stress5.mls
+tape0.dev
+tape1.dev
+tape2.dev
+tape3.dev
+tape4.dev
+tape5.dev
+tape6.dev
+tape7.dev
diff --git a/samples/Makefile.am b/samples/Makefile.am
new file mode 100644
index 0000000..0d452a1
--- /dev/null
+++ b/samples/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright (C) 2000 Jose Antonio Ortega Ruiz <jaortega@retemail.es>
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+EXTRA_DIST =*.mixal primes.result
+
diff --git a/samples/hello.mixal b/samples/hello.mixal
new file mode 100644
index 0000000..6a4c3c1
--- /dev/null
+++ b/samples/hello.mixal
@@ -0,0 +1,11 @@
+* mixal hello world
+*
+TERM EQU 19
+ ORIG 3000
+START OUT MSG(TERM)
+ HLT
+MSG ALF "MIXAL"
+ ALF " HELL"
+ ALF "O WOR"
+ ALF "LD "
+ END START
diff --git a/samples/primes.mixal b/samples/primes.mixal
new file mode 100644
index 0000000..d8e6eef
--- /dev/null
+++ b/samples/primes.mixal
@@ -0,0 +1,54 @@
+* table of primes (taopc p. 148)
+*
+L EQU 500
+OUTDEV EQU 20 the paper tape
+PRIME EQU -1
+BUF0 EQU 2000
+BUF1 EQU BUF0+25
+ ORIG 3000
+START IOC 0(OUTDEV)
+ LD1 =1-L=
+ LD2 =3=
+2H INC1 1
+ ST2 PRIME+L,1
+ J1Z 2F
+4H INC2 2
+ ENT3 2
+6H ENTA 0
+ ENTX 0,2
+ DIV PRIME,3
+ JXZ 4B
+ CMPA PRIME,3
+ INC3 1
+ JG 6B
+ JMP 2B
+2H OUT TITLE(OUTDEV)
+ ENT4 BUF1+10
+ ENT5 -50
+2H INC5 L+1
+4H LDA PRIME,5
+ CHAR
+ STX 0,4(1:4)
+ DEC4 1
+ DEC5 50
+ J5P 4B
+ OUT 0,4(OUTDEV)
+ LD4 24,4
+ J5N 2B
+ HLT
+* initial contents
+ ORIG PRIME+1
+ CON 2
+ ORIG BUF0-5
+TITLE ALF "FIRST"
+ ALF " FIVE"
+ ALF " HUND"
+ ALF "RED P"
+ ALF "RIMES"
+ ORIG BUF0+24
+ CON BUF1+10
+ ORIG BUF1+24
+ CON BUF0+10
+ END START
+
+ \ No newline at end of file
diff --git a/samples/primes.result b/samples/primes.result
new file mode 100644
index 0000000..1431f77
--- /dev/null
+++ b/samples/primes.result
@@ -0,0 +1,51 @@
+FIRST FIVE HUNDRED PRIMES
+ 0002 0233 0547 0877 1229 1597 1993 2371 2749 3187
+ 0003 0239 0557 0881 1231 1601 1997 2377 2753 3191
+ 0005 0241 0563 0883 1237 1607 1999 2381 2767 3203
+ 0007 0251 0569 0887 1249 1609 2003 2383 2777 3209
+ 0011 0257 0571 0907 1259 1613 2011 2389 2789 3217
+ 0013 0263 0577 0911 1277 1619 2017 2393 2791 3221
+ 0017 0269 0587 0919 1279 1621 2027 2399 2797 3229
+ 0019 0271 0593 0929 1283 1627 2029 2411 2801 3251
+ 0023 0277 0599 0937 1289 1637 2039 2417 2803 3253
+ 0029 0281 0601 0941 1291 1657 2053 2423 2819 3257
+ 0031 0283 0607 0947 1297 1663 2063 2437 2833 3259
+ 0037 0293 0613 0953 1301 1667 2069 2441 2837 3271
+ 0041 0307 0617 0967 1303 1669 2081 2447 2843 3299
+ 0043 0311 0619 0971 1307 1693 2083 2459 2851 3301
+ 0047 0313 0631 0977 1319 1697 2087 2467 2857 3307
+ 0053 0317 0641 0983 1321 1699 2089 2473 2861 3313
+ 0059 0331 0643 0991 1327 1709 2099 2477 2879 3319
+ 0061 0337 0647 0997 1361 1721 2111 2503 2887 3323
+ 0067 0347 0653 1009 1367 1723 2113 2521 2897 3329
+ 0071 0349 0659 1013 1373 1733 2129 2531 2903 3331
+ 0073 0353 0661 1019 1381 1741 2131 2539 2909 3343
+ 0079 0359 0673 1021 1399 1747 2137 2543 2917 3347
+ 0083 0367 0677 1031 1409 1753 2141 2549 2927 3359
+ 0089 0373 0683 1033 1423 1759 2143 2551 2939 3361
+ 0097 0379 0691 1039 1427 1777 2153 2557 2953 3371
+ 0101 0383 0701 1049 1429 1783 2161 2579 2957 3373
+ 0103 0389 0709 1051 1433 1787 2179 2591 2963 3389
+ 0107 0397 0719 1061 1439 1789 2203 2593 2969 3391
+ 0109 0401 0727 1063 1447 1801 2207 2609 2971 3407
+ 0113 0409 0733 1069 1451 1811 2213 2617 2999 3413
+ 0127 0419 0739 1087 1453 1823 2221 2621 3001 3433
+ 0131 0421 0743 1091 1459 1831 2237 2633 3011 3449
+ 0137 0431 0751 1093 1471 1847 2239 2647 3019 3457
+ 0139 0433 0757 1097 1481 1861 2243 2657 3023 3461
+ 0149 0439 0761 1103 1483 1867 2251 2659 3037 3463
+ 0151 0443 0769 1109 1487 1871 2267 2663 3041 3467
+ 0157 0449 0773 1117 1489 1873 2269 2671 3049 3469
+ 0163 0457 0787 1123 1493 1877 2273 2677 3061 3491
+ 0167 0461 0797 1129 1499 1879 2281 2683 3067 3499
+ 0173 0463 0809 1151 1511 1889 2287 2687 3079 3511
+ 0179 0467 0811 1153 1523 1901 2293 2689 3083 3517
+ 0181 0479 0821 1163 1531 1907 2297 2693 3089 3527
+ 0191 0487 0823 1171 1543 1913 2309 2699 3109 3529
+ 0193 0491 0827 1181 1549 1931 2311 2707 3119 3533
+ 0197 0499 0829 1187 1553 1933 2333 2711 3121 3539
+ 0199 0503 0839 1193 1559 1949 2339 2713 3137 3541
+ 0211 0509 0853 1201 1567 1951 2341 2719 3163 3547
+ 0223 0521 0857 1213 1571 1973 2347 2729 3167 3557
+ 0227 0523 0859 1217 1579 1979 2351 2731 3169 3559
+ 0229 0541 0863 1223 1583 1987 2357 2741 3181 3571
diff --git a/samples/stress1.mixal b/samples/stress1.mixal
new file mode 100644
index 0000000..f9bc8c9
--- /dev/null
+++ b/samples/stress1.mixal
@@ -0,0 +1,9 @@
+ ORIG 1999
+ST NOP
+3H EQU 69
+3H ENTA 3B
+** According to pg 151, rA should be 69, not 2000
+** "An address of 2F or 2B never refers to its own line"
+ HLT
+ END ST
+
diff --git a/samples/stress2.mixal b/samples/stress2.mixal
new file mode 100644
index 0000000..4c7250d
--- /dev/null
+++ b/samples/stress2.mixal
@@ -0,0 +1,14 @@
+ ORIG 1999
+ST NOP
+3H CON 10
+ ENT1 *
+ LDA 3B
+** rI1 is 2001, rA is 10. So far so good!
+3H ORIG 3B-1000
+** at this point 3H should
+** equal 2002, and the location counter should be 1000.
+ ENT2 *
+ LDX 3B
+** rI2 should be 1000, rX should be 2002 (I think...)
+ HLT
+ END ST
diff --git a/samples/stress4.mixal b/samples/stress4.mixal
new file mode 100644
index 0000000..7bcdd2a
--- /dev/null
+++ b/samples/stress4.mixal
@@ -0,0 +1,7 @@
+ ORIG 2000
+ST NOP
+ ENTA FUT
+** Whoa, mdk tells me FUT is never defined...
+FUT EQU 69
+ HLT
+ END ST