From 300160e73da486946ae513f1d039dcd7b85ff17c Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Mon, 20 Mar 2006 22:46:46 +0000 Subject: Version 1.2.1 imported git-archimport-id: mdk@sv.gnu.org/mdk--devel--1--patch-1 --- AUTHORS | 14 + COPYING | 340 +++ ChangeLog | 431 ++++ ChangeLog.1 | 1807 ++++++++++++++++ INSTALL | 339 +++ Makefile.am | 24 + NEWS | 450 ++++ README | 43 + THANKS | 59 + TODO | 19 + autogen.sh | 79 + configure.in | 175 ++ doc/Makefile.am | 23 + doc/gendocs.sh | 285 +++ doc/gendocs_template | 100 + doc/img/Makefile.am | 16 + doc/img/ss_devdir.jpg | Bin 0 -> 5344 bytes doc/img/ss_devform.jpg | Bin 0 -> 6995 bytes doc/img/ss_devices.jpg | Bin 0 -> 74404 bytes doc/img/ss_extprog.jpg | Bin 0 -> 10282 bytes doc/img/ss_mix.jpg | Bin 0 -> 50408 bytes doc/img/ss_mix.txt | 31 + doc/img/ss_mixal.jpg | Bin 0 -> 60476 bytes doc/img/ss_split.jpg | Bin 0 -> 143101 bytes doc/img/ss_symbols.jpg | Bin 0 -> 13691 bytes doc/img/ss_worddlg.jpg | Bin 0 -> 7916 bytes doc/mdk.texi | 248 +++ doc/mdk_ack.texi | 63 + doc/mdk_bugs.texi | 24 + doc/mdk_copying.texi | 866 ++++++++ doc/mdk_emacs.texi | 136 ++ doc/mdk_findex.texi | 11 + doc/mdk_gmixvm.texi | 394 ++++ doc/mdk_gstart.texi | 1058 ++++++++++ doc/mdk_index.texi | 14 + doc/mdk_install.texi | 287 +++ doc/mdk_intro.texi | 70 + doc/mdk_mixasm.texi | 89 + doc/mdk_mixguile.texi | 445 ++++ doc/mdk_mixvm.texi | 813 ++++++++ doc/mdk_tut.texi | 1319 ++++++++++++ lib/Makefile.am | 17 + lib/getopt.h | 129 ++ lib/getopt_long.c | 1086 ++++++++++ mdk.spec | 142 ++ misc/Makefile.am | 16 + misc/mixal-mode.el | 1321 ++++++++++++ misc/mixvm.el | 158 ++ mixgtk/Makefile.am | 47 + mixgtk/gmixvm.c | 124 ++ mixgtk/mixgtk.c | 79 + mixgtk/mixgtk.glade | 3913 +++++++++++++++++++++++++++++++++++ mixgtk/mixgtk.gladep | 9 + mixgtk/mixgtk.h | 49 + mixgtk/mixgtk_cmd_dispatcher.c | 547 +++++ mixgtk/mixgtk_cmd_dispatcher.h | 61 + mixgtk/mixgtk_config.c | 113 + mixgtk/mixgtk_config.h | 70 + mixgtk/mixgtk_device.c | 625 ++++++ mixgtk/mixgtk_device.h | 45 + mixgtk/mixgtk_fontsel.c | 142 ++ mixgtk/mixgtk_fontsel.h | 51 + mixgtk/mixgtk_gen_handlers.c | 165 ++ mixgtk/mixgtk_gen_handlers.h | 62 + mixgtk/mixgtk_input.c | 233 +++ mixgtk/mixgtk_input.h | 49 + mixgtk/mixgtk_mixal.c | 580 ++++++ mixgtk/mixgtk_mixal.h | 66 + mixgtk/mixgtk_mixvm.c | 529 +++++ mixgtk/mixgtk_mixvm.h | 72 + mixgtk/mixgtk_widgets.c | 153 ++ mixgtk/mixgtk_widgets.h | 102 + mixgtk/mixgtk_wm.c | 573 +++++ mixgtk/mixgtk_wm.h | 46 + mixguile/Makefile.am | 43 + mixguile/mixguile-commands.scm | 254 +++ mixguile/mixguile-vm-stat.scm | 71 + mixguile/mixguile.c | 124 ++ mixguile/mixguile.h | 72 + mixguile/mixguile.scm | 25 + mixguile/mixguile_cmd_dispatcher.c | 122 ++ mixguile/mixguile_cmd_dispatcher.h | 57 + mixguile/mixguile_main.c | 94 + mixguile/xmixguile_cmd_dispatcher.c | 558 +++++ mixguile/xmixguile_cmd_dispatcher.h | 67 + mixlib/Makefile.am | 42 + mixlib/gettext.h | 69 + mixlib/mix.c | 99 + mixlib/mix.h | 78 + mixlib/mix_code_file.c | 330 +++ mixlib/mix_code_file.h | 106 + mixlib/mix_config.c | 298 +++ mixlib/mix_config.h | 100 + mixlib/mix_device.c | 164 ++ mixlib/mix_device.h | 160 ++ mixlib/mix_eval.c | 191 ++ mixlib/mix_eval.h | 110 + mixlib/mix_eval_scanner.l | 276 +++ mixlib/mix_file.c | 159 ++ mixlib/mix_file.h | 65 + mixlib/mix_ins.c | 269 +++ mixlib/mix_ins.h | 195 ++ mixlib/mix_io.c | 208 ++ mixlib/mix_io.h | 119 ++ mixlib/mix_parser.c | 605 ++++++ mixlib/mix_parser.h | 111 + mixlib/mix_predicate.c | 215 ++ mixlib/mix_predicate.h | 80 + mixlib/mix_predicate_list.c | 117 ++ mixlib/mix_predicate_list.h | 64 + mixlib/mix_scanner.l | 581 ++++++ mixlib/mix_src_file.c | 157 ++ mixlib/mix_src_file.h | 57 + mixlib/mix_symbol_table.c | 198 ++ mixlib/mix_symbol_table.h | 109 + mixlib/mix_types.c | 569 +++++ mixlib/mix_types.h | 293 +++ mixlib/mix_vm.c | 706 +++++++ mixlib/mix_vm.h | 255 +++ mixlib/mix_vm_clock.c | 70 + mixlib/mix_vm_clock.h | 55 + mixlib/mix_vm_command.c | 641 ++++++ mixlib/mix_vm_command.h | 256 +++ mixlib/mix_vm_dump.c | 147 ++ mixlib/mix_vm_dump.h | 91 + mixlib/testsuite/Makefile.am | 32 + mixlib/testsuite/mix_device_t.c | 76 + mixlib/testsuite/mix_eval_t.c | 119 ++ mixlib/testsuite/mix_ins_t.c | 79 + mixlib/testsuite/mix_parser_t.c | 85 + mixlib/testsuite/mix_types_t.c | 369 ++++ mixlib/testsuite/mix_vm_ins_t.c | 505 +++++ mixlib/testsuite/test.h | 44 + mixlib/xmix_device.c | 199 ++ mixlib/xmix_device.h | 96 + mixlib/xmix_eval.h | 55 + mixlib/xmix_io.c | 57 + mixlib/xmix_io.h | 64 + mixlib/xmix_parser.h | 111 + mixlib/xmix_vm.c | 598 ++++++ mixlib/xmix_vm.h | 139 ++ mixlib/xmix_vm_command.c | 64 + mixlib/xmix_vm_command.h | 102 + mixlib/xmix_vm_handlers.c | 1387 +++++++++++++ mixlib/xmix_vm_handlers.h | 87 + mixutils/Makefile.am | 27 + mixutils/mixasm.c | 136 ++ mixutils/mixasm_comp.c | 72 + mixutils/mixasm_comp.h | 35 + mixutils/mixvm.c | 150 ++ mixutils/mixvm_command.c | 270 +++ mixutils/mixvm_command.h | 38 + mixutils/mixvm_loop.c | 160 ++ mixutils/mixvm_loop.h | 38 + po/ChangeLog | 143 ++ po/LINGUAS | 2 + po/Makevars | 25 + po/POTFILES.in | 27 + po/de.po | 1553 ++++++++++++++ samples/Makefile.am | 16 + samples/echo.mixal | 10 + samples/hello.mixal | 11 + samples/m.mixal | 25 + samples/permutations.cardrd | 3 + samples/permutations.mixal | 89 + samples/primes.mixal | 53 + samples/primes.result | 51 + samples/tests/bt.mixal | 6 + samples/tests/cbp.mixal | 14 + samples/tests/ldan.mixal | 5 + samples/tests/lockonw.mixal | 3 + samples/tests/negwrite.mixal | 4 + samples/tests/stress0.mixal | 8 + samples/tests/stress1.mixal | 9 + samples/tests/stress2.mixal | 7 + samples/tests/stress4.mixal | 7 + samples/tests/stress5.mixal | 17 + samples/tests/stress6.mixal | 9 + updatelog | 1 + 179 files changed, 38640 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 ChangeLog.1 create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 THANKS create mode 100644 TODO create mode 100755 autogen.sh create mode 100644 configure.in create mode 100644 doc/Makefile.am create mode 100755 doc/gendocs.sh create mode 100644 doc/gendocs_template create mode 100644 doc/img/Makefile.am create mode 100644 doc/img/ss_devdir.jpg create mode 100644 doc/img/ss_devform.jpg create mode 100644 doc/img/ss_devices.jpg create mode 100644 doc/img/ss_extprog.jpg create mode 100644 doc/img/ss_mix.jpg create mode 100644 doc/img/ss_mix.txt create mode 100644 doc/img/ss_mixal.jpg create mode 100644 doc/img/ss_split.jpg create mode 100644 doc/img/ss_symbols.jpg create mode 100644 doc/img/ss_worddlg.jpg create mode 100644 doc/mdk.texi create mode 100644 doc/mdk_ack.texi create mode 100644 doc/mdk_bugs.texi create mode 100644 doc/mdk_copying.texi create mode 100644 doc/mdk_emacs.texi create mode 100644 doc/mdk_findex.texi create mode 100644 doc/mdk_gmixvm.texi create mode 100644 doc/mdk_gstart.texi create mode 100644 doc/mdk_index.texi create mode 100644 doc/mdk_install.texi create mode 100644 doc/mdk_intro.texi create mode 100644 doc/mdk_mixasm.texi create mode 100644 doc/mdk_mixguile.texi create mode 100644 doc/mdk_mixvm.texi create mode 100644 doc/mdk_tut.texi create mode 100644 lib/Makefile.am create mode 100644 lib/getopt.h create mode 100644 lib/getopt_long.c create mode 100644 mdk.spec create mode 100644 misc/Makefile.am create mode 100644 misc/mixal-mode.el create mode 100644 misc/mixvm.el create mode 100644 mixgtk/Makefile.am create mode 100644 mixgtk/gmixvm.c create mode 100644 mixgtk/mixgtk.c create mode 100644 mixgtk/mixgtk.glade create mode 100644 mixgtk/mixgtk.gladep create mode 100644 mixgtk/mixgtk.h create mode 100644 mixgtk/mixgtk_cmd_dispatcher.c create mode 100644 mixgtk/mixgtk_cmd_dispatcher.h create mode 100644 mixgtk/mixgtk_config.c create mode 100644 mixgtk/mixgtk_config.h create mode 100644 mixgtk/mixgtk_device.c create mode 100644 mixgtk/mixgtk_device.h create mode 100644 mixgtk/mixgtk_fontsel.c create mode 100644 mixgtk/mixgtk_fontsel.h create mode 100644 mixgtk/mixgtk_gen_handlers.c create mode 100644 mixgtk/mixgtk_gen_handlers.h create mode 100644 mixgtk/mixgtk_input.c create mode 100644 mixgtk/mixgtk_input.h create mode 100644 mixgtk/mixgtk_mixal.c create mode 100644 mixgtk/mixgtk_mixal.h create mode 100644 mixgtk/mixgtk_mixvm.c create mode 100644 mixgtk/mixgtk_mixvm.h create mode 100644 mixgtk/mixgtk_widgets.c create mode 100644 mixgtk/mixgtk_widgets.h create mode 100644 mixgtk/mixgtk_wm.c create mode 100644 mixgtk/mixgtk_wm.h create mode 100644 mixguile/Makefile.am create mode 100644 mixguile/mixguile-commands.scm create mode 100644 mixguile/mixguile-vm-stat.scm create mode 100644 mixguile/mixguile.c create mode 100644 mixguile/mixguile.h create mode 100644 mixguile/mixguile.scm create mode 100644 mixguile/mixguile_cmd_dispatcher.c create mode 100644 mixguile/mixguile_cmd_dispatcher.h create mode 100644 mixguile/mixguile_main.c create mode 100644 mixguile/xmixguile_cmd_dispatcher.c create mode 100644 mixguile/xmixguile_cmd_dispatcher.h create mode 100644 mixlib/Makefile.am create mode 100644 mixlib/gettext.h create mode 100644 mixlib/mix.c create mode 100644 mixlib/mix.h create mode 100644 mixlib/mix_code_file.c create mode 100644 mixlib/mix_code_file.h create mode 100644 mixlib/mix_config.c create mode 100644 mixlib/mix_config.h create mode 100644 mixlib/mix_device.c create mode 100644 mixlib/mix_device.h create mode 100644 mixlib/mix_eval.c create mode 100644 mixlib/mix_eval.h create mode 100644 mixlib/mix_eval_scanner.l create mode 100644 mixlib/mix_file.c create mode 100644 mixlib/mix_file.h create mode 100644 mixlib/mix_ins.c create mode 100644 mixlib/mix_ins.h create mode 100644 mixlib/mix_io.c create mode 100644 mixlib/mix_io.h create mode 100644 mixlib/mix_parser.c create mode 100644 mixlib/mix_parser.h create mode 100644 mixlib/mix_predicate.c create mode 100644 mixlib/mix_predicate.h create mode 100644 mixlib/mix_predicate_list.c create mode 100644 mixlib/mix_predicate_list.h create mode 100644 mixlib/mix_scanner.l create mode 100644 mixlib/mix_src_file.c create mode 100644 mixlib/mix_src_file.h create mode 100644 mixlib/mix_symbol_table.c create mode 100644 mixlib/mix_symbol_table.h create mode 100644 mixlib/mix_types.c create mode 100644 mixlib/mix_types.h create mode 100644 mixlib/mix_vm.c create mode 100644 mixlib/mix_vm.h create mode 100644 mixlib/mix_vm_clock.c create mode 100644 mixlib/mix_vm_clock.h create mode 100644 mixlib/mix_vm_command.c create mode 100644 mixlib/mix_vm_command.h create mode 100644 mixlib/mix_vm_dump.c create mode 100644 mixlib/mix_vm_dump.h create mode 100644 mixlib/testsuite/Makefile.am create mode 100644 mixlib/testsuite/mix_device_t.c create mode 100644 mixlib/testsuite/mix_eval_t.c create mode 100644 mixlib/testsuite/mix_ins_t.c create mode 100644 mixlib/testsuite/mix_parser_t.c create mode 100644 mixlib/testsuite/mix_types_t.c create mode 100644 mixlib/testsuite/mix_vm_ins_t.c create mode 100644 mixlib/testsuite/test.h create mode 100644 mixlib/xmix_device.c create mode 100644 mixlib/xmix_device.h create mode 100644 mixlib/xmix_eval.h create mode 100644 mixlib/xmix_io.c create mode 100644 mixlib/xmix_io.h create mode 100644 mixlib/xmix_parser.h create mode 100644 mixlib/xmix_vm.c create mode 100644 mixlib/xmix_vm.h create mode 100644 mixlib/xmix_vm_command.c create mode 100644 mixlib/xmix_vm_command.h create mode 100644 mixlib/xmix_vm_handlers.c create mode 100644 mixlib/xmix_vm_handlers.h create mode 100644 mixutils/Makefile.am create mode 100644 mixutils/mixasm.c create mode 100644 mixutils/mixasm_comp.c create mode 100644 mixutils/mixasm_comp.h create mode 100644 mixutils/mixvm.c create mode 100644 mixutils/mixvm_command.c create mode 100644 mixutils/mixvm_command.h create mode 100644 mixutils/mixvm_loop.c create mode 100644 mixutils/mixvm_loop.h create mode 100644 po/ChangeLog create mode 100644 po/LINGUAS create mode 100644 po/Makevars create mode 100644 po/POTFILES.in create mode 100644 po/de.po create mode 100644 samples/Makefile.am create mode 100644 samples/echo.mixal create mode 100644 samples/hello.mixal create mode 100644 samples/m.mixal create mode 100644 samples/permutations.cardrd create mode 100644 samples/permutations.mixal create mode 100644 samples/primes.mixal create mode 100644 samples/primes.result create mode 100644 samples/tests/bt.mixal create mode 100644 samples/tests/cbp.mixal create mode 100644 samples/tests/ldan.mixal create mode 100644 samples/tests/lockonw.mixal create mode 100644 samples/tests/negwrite.mixal create mode 100644 samples/tests/stress0.mixal create mode 100644 samples/tests/stress1.mixal create mode 100644 samples/tests/stress2.mixal create mode 100644 samples/tests/stress4.mixal create mode 100644 samples/tests/stress5.mixal create mode 100644 samples/tests/stress6.mixal create mode 100755 updatelog diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..7bde8b5 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,14 @@ +Authors of GNU MDK. +See also the files THANKS and ChangeLog. + +Jose A. Ortega Ruiz designed and implemented mdk. + +Pieter E. J. Pareit designed, implemented and documented +mixal-mode.el, and fixed bugs in other mdk code. + +Philip E. King designed and implemented mixvm.el. + +Michael Scholz wrote the German translation po/de.po. + +Sergey Poznyakoff provided patches to mixlib/mix_scanner.l improving +MIXAL compliance. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 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..2991320 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,431 @@ +2005-09-20 Jose Antonio Ortega Ruiz + + * mdk: version 1.2.1 tagged (v1r2_1). + + * doc/mdk_copying.texi: FDL license updated to 1.2. + + * mdk (Module): FSF address updated. + + * mixguile/xmixguile_cmd_dispatcher.c (Module): use unsigned int + for length parameters. + + * doc/mdk_tut.texi: compliance with 'traditional' ALF directive + documented. + +2005-09-19 Jose Antonio Ortega Ruiz + + * po/de.po: corrections by Jens Seidel. + + * mixgtk/Makefile.am (AM_LDFLAGS): fix libglade dynamic linking. + + * mixutils/mixasm.c:improve -g handling (accept it to not break + potential user scripts) + +2005-04-05 Pieter Pareit + + * mixutils/mixasm.c: make handeling of arguments somewhat robuster. + + * misc/mixal-mode.el: -g option no longer needed on compilation. + + * doc/mdk_mixasm.texi: fix of grammer mistake. + +2005-03-26 Sergey Poznyakoff + + * mixlib/mix_scanner.l (ENTER_WEVAL) Accept an argument, specifying + how many characters to exclude from yyless. + (ws): Removed '+' closure. Throughout the code this macro is used + as {ws}+ or {ws}*, so it is superfluous. + (%{...%} block) [FLEX_DEBUG]: Set yy_flex_debug from the environment + variable. Useful for debugging. + (ALF): Pad with spaces arguments shorter than 5 characters + Accept traditional ALF syntax (withoutq quotes) + (
): Accept w-expressions in literals (between = =). + +2004-08-05 Jose Antonio Ortega Ruiz + + * mdk: version 1.2 tagged (v1r2). + + * Makefile.am: distclean-local rule added to handle intltool + products and make distcheck happy. + +2004-08-03 Jose Antonio Ortega Ruiz + + * doc: documentation cleanup. + +2004-08-02 Jose Antonio Ortega Ruiz + + * INSTALL: + * doc/mdk_install.texi: new library dependencies. + + * doc/mdk_gmixvm.texi: new gui documentation. + + * configure.in: -fno-strict-aliasing. + + * mixgtk/mixgtk_cmd_dispatcher.c (on_external_programs_activate): + new-style handling of the external programs dialog. + + * mixlib/mix_parser.c (mix_parser_delete): + * mixlib/mix_vm.c (mix_vm_get_lineno_address): g_tree_foreach + instead of deprecated g_tree_traverse. + +2004-08-01 Jose Antonio Ortega Ruiz + + * mixutils/mixvm_command.c (init_dis_): + * mixgtk/mixgtk_cmd_dispatcher.c (read_config_): -g option not + needed by mixasm. + (mixgtk_cmd_dispatcher_init): do not redirect stderr to the + command log windows. + + * doc/mdk_mixasm.texi (Invoking @code{mixasm}): document -O option. + +2004-07-30 Jose Antonio Ortega Ruiz + + * mixutils/mixasm.c (main): new option -O to disable debug, which + is now enabled by default. + + * configure.in: check also for libpango. + +2004-07-11 Jose Antonio Ortega Ruiz + + * mixgtk/mixgtk_cmd_dispatcher.c (complete_command_) + (on_command_prompt_key_press_event): fixed cursor position after + completion. + +2004-07-10 Jose Antonio Ortega Ruiz + + * po/POTFILES.in: + * configure.in: + * autogen.sh: + * Makefile.am: use intltool to allow glade file string translations. + + * mixgtk/Makefile.am (-DLOCAL_GLADE_FILE): really allow off-tree builds. + +2004-07-05 Jose Antonio Ortega Ruiz + + * mixgtk/mixgtk_wm.c: preserve order of detachable windows when + reatached. + + * mixgtk/mixgtk_mixvm.c: + * mixgtk/mixgtk_mixal.{hc}: + * mixgtk/mixgtk_fontsel.{hc}: + * mixgtk/mixgtk_device.{hc}: + * mixgtk/mixgtk_cmd_dispatcher.{hc}: + * mixgtk/mixgtk.glade: new menu item to change all fonts at once, + and the symbol list font. + +2004-07-02 Jose Antonio Ortega Ruiz + + * mixgtk/mixgtk_wm.{hc}: toolbar visibility and new attach all + toolbar button. + + * mixgtk/mixgtk_mixvm.c: go to dialog handling simplified. + + * mixgtk/mixgtk_cmd_dispatcher.c (log_command_): correctly place + cursor before insertion. + + * mixgtk/mixgtk_device.c (write_char_): scroll on output and + cursor placement. + +2004-06-30 Jose Antonio Ortega Ruiz + + * autogen.sh: do not run configure. + + * mixgtk/Makefile.am (-DLOCAL_GLADE_FILE): allow off-tree builds. + + * mixgtk/mixgtk_wm.c (on_nb_switch_): warning on null widget page + fixed. + + * mixgtk/*.xpm: + * mixgtk/Makefile.am (Module): only stock icons are used now. + + * mixgtk/mixgtk_wm.{hc}: + * mixgtk/mixgtk_widgets.{hc}: + * mixgtk/mixgtk_mixvm.{hc}: + * mixgtk/mixgtk_mixal.{hc}: + * mixgtk/mixgtk_device.{hc}: + * mixgtk/mixgtk_config.{hc}: + * mixgtk/mixgtk.{hc}: + * mixgtk/mixgtk.glade: all the old functionality, including + slipit mode revamped as detachable windows in place using gtk+2. + Still some rough borders to polish, probably. + +2004-06-24 Jose Antonio Ortega Ruiz + + * mixgtk/mixgtk_widgets.{hc}: + * mixgtk/mixgtk_mixvm.c: + * mixgtk/mixgtk_mixal.c: + * mixgtk/mixgtk_fontsel.{hc}: + * mixgtk/mixgtk_device.{hc}: + * mixgtk/mixgtk_cmd_dispatcher.c: + * mixgtk/mixgtk.glade: + * mixgtk/mixgtk.c: almost complete (barring bugs) reimplementation + of all gmixvm functionality in non-split mode for gtk 2.4.x. + +2004-06-23 Jose Antonio Ortega Ruiz + + * mixgtk (Module): first, incomplete port to gtk 2.4.x. Basic + functionality in place. + + * mixguile/xmixguile_cmd_dispatcher.c (Module): + * mixlib (Module): update to glib 2.x. + + * mixgtk/mixgtk_colorsel.h (Module): + * mixgtk/mixgtk_colorsel.c (Module): removed (no longer used). + + * configure.in (Module): default help messages for disable/enable + features (Adrian). Port to pkg-config and gtk+2. + + * mixlib/mix_vm.c (vm_reset_reload_): do not delete output char + devices after reload. + +2004-06-22 Jose Antonio Ortega Ruiz + + * mixlib/mix_parser.c: do not store bogus line number for added + CON instructions. + +2004-06-12 Jose Antonio Ortega Ruiz + + * mdk (Module): version 1.1 tagged (v1r1). + + * mixlib/xmix_parser.h (Module): + * mixlib/mix_scanner.l (Module): + * mixlib/mix_parser.c (Module): recognition of ALF in listings. + + * mixlib/mix_io.c (mix_io_write_word_array_as_char): drop bogus + EOF comparison. + +2004-06-12 Jose Antonio Ortega Ruiz + + * configure.in (Module): new version; fix guile checking. + + * doc/mdk_mixvm.texi (Devices): + * mixlib/xmix_device.c: the paper tape is really an input device. + + * mixgtk/mixgtk_widgets.h (Module): + * mixgtk/mixgtk_widgets.c (Module): + * mixgtk/mixgtk_device.c (Module): + * mixgtk/mixgtk.glade (Module): support for terminal device input + in the form of a new dialog. + +2004-06-10 Jose Antonio Ortega Ruiz + + * mixlib/mix_parser.c (mix_parser_compile): correctly set the loc + pointer. + + * mixlib/mix_io.c (Module): allow truncated lines in char input + device files. + + * mixlib/testsuite/mix_types_t.c (Module): test char to byte + conversions. + + * mixlib/mix_types.c (Module): + * doc/mdk_tut.texi (Module): new ASCII rep for delta, sigma + and pi. + + * mixlib/testsuite/mix_vm_ins_t.c (Module): + * mixlib/testsuite/mix_types_t.c (Module): adaptation to new + character set and LDN instructions behaviour. + +2004-06-09 Jose Antonio Ortega Ruiz + + * doc/mdk_mixvm.texi (Devices): documentation for the console i/o. + + * mixlib/mix_io.{hc}: + * mixlib/mix_device.h: + * mixlib/xmix_device.{hc}: the console is now in/out + +2004-06-07 Jose Antonio Ortega Ruiz + + * mixlib/mix_symbol_table.c (print_sym_rows_): align symbol values. + + * mixutils/mixasm.c: correct usage message. + + * mixlib/mix_scanner.l (Module): fix for bug #5654, including + support for both field specs and indexing in local constants. + + * mixlib/mix_parser.c (Module): produce better listings, + identifying trailing CON instructions. + + * mixutils/mixvm_loop.c (Module): + * mixlib/mix_config.c (Module): always use prompts ending in + whitespace. + + * mixutils/mixvm_loop.c (mix_vmrun): do not save command line + options when -r is passed to mixvm. + + * doc/mdk_mixvm.texi (Devices): documentation for the changes below. + + * mixlib/mix_types.c (mix_ascii_to_char): accept lower case + characters. + + * mixlib/xmix_device.c (read_): blocks in input char devices must + be separated by newline characters. + + * mixlib/mix_vm.c (Module): correct error tracking and reporting. + + * mixlib/mix_parser.{ch} (Module): properly treat undefined + forward references, inserting new addresses at the program's end. + +2004-06-06 Jose Antonio Ortega Ruiz + + * mixlib/xmix_vm_handlers.c (Module): + * mixlib/xmix_vm.{hc} (Module): keep track of runtime errors and + correctly report them. + + * mixlib/mix_io.c (Module): bug fix: read only worked in debug mode; + more robust error reporting. + + * mixlib/xmix_parser.h (Module): + * mixlib/mix_scanner.l (Module): keep track of program's end + address. + +2004-06-05 Jose Antonio Ortega Ruiz + + * THANKS: + * doc/mdk_ack.texi (Acknowledgments): reorganisation. + + * mixlib/xmix_vm.c (lda_handler_): always reverse sign in LDAN, + LDXN and LDiN, even if fspec is not zero (Ruslan Batdalov, closes + Debian bug #247392). + + * autogen.sh: error messages improved and autotools versions updated. + +2004-01-09 Jose Antonio Ortega Ruiz + + * configure.in: check for guile headers. + +2003-06-09 Jose A Ortega Ruiz + + * mdk (Module): version 1.0.1 tagged (v1r0_1) and released. + +2003-06-09 Jose A Ortega Ruiz + + * misc/Makefile.am (pkgdata_DATA): include mixal-mode.el in the + distribution and install it. + + * doc/mdk_ack.texi: + * THANKS: Eli added. + +2003-06-06 Jose A Ortega Ruiz + + * doc/mdk_tut.texi (Shift operators): SLC and SRC act on AX, not + on A. + (Conversion operators): correct description of digit + representation. + +2003-06-04 Jose A Ortega Ruiz + + * doc: documentation for emacs support merged in one file + (mdk_emacs.texi), substituting mdk_emixvm.texi and + mdk_mixal-mode.texi. + + * mixlib/mix_code_file.c (mix_code_file_new_): properly initialise + source_path pointer to NULL, preventing later deletion of an + uninitialised pointer (which caused a segfault). + +2003-06-03 Jose A Ortega Ruiz + + * AUTHORS: Added Pieter Pareit. + + * doc/mdk_ack.texi (Acknowledgments): + * THANKS: Thanks to P. E. J. Pareit, N. H. F. Beebe and Ronald Cole. + + * doc/mdk_install.texi (Supported platforms): added platforms + tested by N. H. F. Beebe. + + * doc/mdk_mixal-mode.texi (mixal-mode.el): minor editing of + Pieter's original documentation. + + * doc/mdk_tut.texi (Address transfer operators): mixed bug in + DECX's MOD value. + +2003-05-28 Jose A Ortega Ruiz + + * mixlib/mix_scanner.l, mixlib/mix_parser.h, mixlib/mix_parser.c: + new error message for missing ALF operand quotes (bug #3750 fixed) + +2003-04-06 Jose A Ortega Ruiz + + * mixguile/xmixguile_cmd_dispatcher.c: Missing standard header for + strlen #included. + +2003-02-13 Pieter E J Pareit + + * mixguile/xmixguile_cmd_dispatcher.c: bug fix: mix_reg_() and + mix_set_reg_() did not convert argument to string if it was a + symbol. + +2003-01-17 Pieter E J Pareit + + * misc/mixal-mode.el: bug fix: a regex was missing a '-'. + + * doc/mdk_mixal-mode.texi: added documentation for mixal-mode.el. + + * doc/mdk.texi: updated menu to include documentation for mixal-mode.el. + + * doc/mdk_emixvm.texi: updated nodes to include mixal-mode.el. + + * doc/mdk_egstart.texi: updated nodes to include mixal-mode.el. + + * doc/mdk_install.texi: added documentation to node 'Emacs support'. + +2003-01-12 Jose A Ortega Ruiz + + * mixlib/xmix_vm.h (inc_loc_): Stop program execution if the + program counter is incremented beyond the maximum address (3999). + +2003-01-11 Jose A Ortega Ruiz + + * mixlib/xmix_vm_handlers.c: Bug #1704 fixed. + + * doc/mdk_mixguile.texi (mixvm wrappers): Bug #1703 fixed. + + * misc/mixal-mode.el (Module): new emacs mode written by Pieter Pareit. + + * misc/mixvm.el: bug fix: correctly detect the absence of menu bar. + +2002-12-08 Jose A Ortega Ruiz + + * Makefile.am, aclocal.m4, configure.in, mixlib/gettext.h, + mixlib/mix.h: corrections to gettext infrastructure. + +2002-12-08 Jose A Ortega Ruiz + + * autogen.sh: use autopoint instead of gettextize. + +2002-10-19 Jose A Ortega Ruiz + + * THANKS: Vasilij removed, as he requested. + +2002-04-11 Jose A Ortega Ruiz + + * mixgtk/gmixvm.c, mixgtk/mixgtk.c, mixgtk/mixgtk_device.c, + mixgtk/mixgtk_gen_handlers.c, mixgtk/mixgtk_mixal.c, + mixgtk/mixgtk_mixvm.c, mixguile/mixguile.c, mixlib/mix.c, + mixlib/mix_config.c, mixlib/mix_predicate.c, + mixlib/mix_vm_command.c, mixutils/mixvm_command.c: + + _() i18n macro added to all strings missing it. + +2002-04-11 Jose A Ortega Ruiz + + * po/POTFILES.in: file list updated. + +2002-04-10 Jose A Ortega Ruiz + + * mixgtk/: mixgtk_mixal.c, mixgtk_mixvm.c: sprintf -> g_snprintf. + +2002-04-10 Jose A Ortega Ruiz + + * mixlib/xmix_vm_handlers.c: bug fix in 'load' command. + +2002-04-10 Jose A Ortega Ruiz + + * mixgtk/mixgtk_cmd_dispatcher.c, mixgtk/mixgtk_device.c, + mixgtk/mixgtk_input.c, mixgtk/mixgtk_mixal.c, + mixgtk/mixgtk_mixvm.c, mixguile/xmixguile_cmd_dispatcher.c, + mixlib/mix_predicate.c, mixlib/mix_vm_command.c, + mixlib/xmix_vm_command.c, mixlib/xmix_vm_handlers.c: + + portability fix: snprintf -> g_snprintf. + diff --git a/ChangeLog.1 b/ChangeLog.1 new file mode 100644 index 0000000..b3d4c3c --- /dev/null +++ b/ChangeLog.1 @@ -0,0 +1,1807 @@ +***** Changes up to version 1.0 ****** + +2002-04-08 03:06 jao + + * NEWS: + + date added + +2002-04-08 02:33 jao + + * mixutils/mixvm_loop.c: + + configurable prompt support + +2002-04-08 02:32 jao + + * mixutils/mixvm_command.c: + + new command: prompt + +2002-04-08 02:32 jao + + * mixutils/mixvm_command.h: + + $Id: ChangeLog.1,v 1.1 2003/02/01 23:07:02 jao Exp $ tag added + +2002-04-08 02:31 jao + + * mixutils/mixvm.c: + + new option (-t/--time) + +2002-04-08 02:30 jao + + * mixutils/Makefile.am: + + new file + +2002-04-08 02:29 jao + + * INSTALL, NEWS, README, THANKS, aclocal.m4, configure.in: + + candidate release 1.0 + +2002-04-08 02:26 jao + + * doc/: mdk_mixvm.texi, mdk_tut.texi, mdk.texi, mdk_ack.texi, + mdk_gstart.texi, mdk_install.texi: + + candidate release 1.0 + +2002-04-08 00:22 jao + + * mixutils/mixvm_loop.h: + + initial revision + +2002-03-29 17:31 jao + + * mixgtk/mixgtk.c: + + $Id: ChangeLog.1,v 1.1 2003/02/01 23:07:02 jao Exp $ tag added + +2002-03-29 17:30 jao + + * mixgtk/: gmixvm.c, mixgtk.c, mixgtk_config.c, mixgtk_device.c, + mixgtk_wm.c: + + missing standard headers included + +2002-03-24 02:22 jao + + * mixlib/mix_code_file.c: + + version compatibility check disabled + +2002-03-24 01:23 jao + + * mixlib/xmix_vm.h: + + wrapping up location pointer when address 3999 is reached + +2002-03-24 01:22 jao + + * samples/.cvsignore: + + new ignored files + +2002-03-20 02:33 jao + + * configure.in: + + copyright an cvs Id + +2002-03-20 02:31 jao + + * po/ChangeLog: + + new gettext version + +2002-03-20 02:30 jao + + * mixutils/: mixasm.c, mixvm.c, mixvm_loop.c: + + new option -t (--time) + +2002-03-20 02:28 jao + + * configure.in: + + correctly grouping commands inside [] + +2002-03-19 23:55 jao + + * mixlib/mix_parser.c: + + comment corrected + +2002-03-19 23:38 jao + + * doc/: mdk_gstart.texi, mdk_tut.texi: + + fxn suggestions + +2002-03-19 23:36 jao + + * .cvsignore, mixgtk/.cvsignore, mixutils/.cvsignore, + samples/.cvsignore: + + new ignored files + +2001-09-30 22:29 jao + + * mixguile/Makefile.am: + + scm init file added + +2001-09-29 04:11 jao + + * ChangeLog: + + release 0.5 + +2001-09-29 03:56 jao + + * NEWS: + + version 0.5 update + +2001-09-29 03:55 jao + + * doc/mdk_gmixvm.texi: + + exclude images in dvi + +2001-09-29 03:54 jao + + * mixlib/mix.h: + + CVS $Id: ChangeLog.1,v 1.1 2003/02/01 23:07:02 jao Exp $ added + +2001-09-29 03:53 jao + + * doc/Makefile.am, mixgtk/Makefile.am, mixguile/Makefile.am, + mixlib/Makefile.am, mixlib/testsuite/Makefile.am, + mixutils/Makefile.am, samples/Makefile.am: + + INCLUDES fixed to allow VPATH builds + +2001-09-29 01:29 jao + + * NEWS, NEWS: + + version 0.5 update + +2001-09-29 01:11 jao + + * TODO, doc/Makefile.am, doc/mdk.texi, doc/mdk_gmixvm.texi, + doc/mdk_mixguile.texi: + + version 0.5 update + +2001-09-29 01:10 jao + + * mixgtk/gmixvm.c, mixguile/mixguile.c, mixguile/mixguile.h, + mixguile/mixguile_main.c, mixlib/mix.c, mixlib/mix.h, + mixutils/mixasm.c, mixutils/mixvm.c: + + uniform command line options handling + +2001-09-27 01:15 jao + + * doc/: mdk.texi, mdk_gstart.texi, mdk_install.texi, + mdk_mixasm.texi, mdk_mixvm.texi, mdk_tut.texi: + + minor cosmetic changes + +2001-09-27 01:13 jao + + * doc/mdk_mixguile.texi: + + partial doc update + +2001-09-26 00:46 jao + + * TODO: + + $Id: ChangeLog.1,v 1.1 2003/02/01 23:07:02 jao Exp $ cvs tag + +2001-09-26 00:45 jao + + * TODO: + + new todo items + +2001-09-26 00:43 jao + + * po/ChangeLog: + + gettextize new entry + +2001-09-26 00:41 jao + + * mixguile/.cvsignore: + + new ignored files + +2001-09-25 23:41 jao + + * mixguile/xmixguile_cmd_dispatcher.c: + + new scheme primitive (mix-last-result) + +2001-09-25 01:27 jao + + * mixguile/: mixguile.c, mixguile.h, mixguile_main.c: + + optionally load local startup file + +2001-09-25 01:27 jao + + * mixutils/: mixvm.c, mixvm_loop.c: + + -q option added + +2001-09-25 01:26 jao + + * mixlib/mix.c: + + GPL notice shortened + +2001-09-19 00:55 jao + + * TODO: + + new todo items + +2001-09-19 00:53 jao + + * NEWS, doc/mdk.texi, doc/mdk_bugs.texi, doc/mdk_emixvm.texi, + doc/mdk_gmixvm.texi, doc/mdk_gstart.texi, doc/mdk_mixasm.texi, + doc/mdk_mixguile.texi, doc/mdk_mixvm.texi: + + partial doc update + +2001-09-19 00:51 jao + + * doc/.cvsignore: + + new ignored file + +2001-09-19 00:51 jao + + * mixgtk/mixgtk_fontsel.c: + + remove fonts that cannot be loaded from the config file + +2001-09-19 00:50 jao + + * mixgtk/: mixgtk_config.c, mixgtk_config.h: + + (mixgtk_config_remove) new function to remove configuration items + +2001-09-19 00:49 jao + + * mixlib/: mix_config.c, mix_config.h: + + (mix_config_remove) new function to remove configuration items + +2001-09-18 23:49 jao + + * mixgtk/mixgtk_fontsel.c: + + use of $Id: ChangeLog.1,v 1.1 2003/02/01 23:07:02 jao Exp $ + +2001-09-18 23:49 jao + + * mixgtk/mixgtk_fontsel.c: + + loc widget fonts are updated correctly + +2001-09-18 01:36 jao + + * doc/mdk_mixvm.texi: + + new mixvm commands documented + +2001-09-18 01:26 jao + + * mixlib/xmix_vm_handlers.c: + + (cmd_pstat_) alway print an endline character + +2001-09-17 00:47 jao + + * mixguile/xmixguile_cmd_dispatcher.c: + + virtual machine status + +2001-09-17 00:43 jao + + * mixguile/mixguile.scm: + + load mixguile-stat-vm.scm + +2001-09-17 00:42 jao + + * mixguile/mixguile-vm-stat.scm: + + header corrected + +2001-09-17 00:40 jao + + * mixguile/.cvsignore, samples/.cvsignore: + + new ignored files + +2001-09-17 00:39 jao + + * mixlib/xmix_vm_command.h: + + minor changes + +2001-09-17 00:38 jao + + * mixlib/xmix_vm.h: + + maintain virtual machine status + +2001-09-17 00:37 jao + + * mixlib/xmix_vm_handlers.h: + + pstat command + +2001-09-17 00:32 jao + + * mixlib/: mix_vm_command.c, mix_vm_command.h: + + minor changes + +2001-09-17 00:29 jao + + * mixlib/: mix_vm.c, mix_vm.h: + + maintain virtual machine status + +2001-09-17 00:28 jao + + * mixlib/: mix_predicate.c, mix_predicate.h, mix_predicate_list.h: + + access to the predicate type added + +2001-09-17 00:17 jao + + * INSTALL, NEWS, doc/.cvsignore, doc/mdk.texi, doc/mdk_ack.texi, + doc/mdk_copying.texi, doc/mdk_gstart.texi, doc/mdk_index.texi, + doc/mdk_install.texi, doc/mdk_intro.texi: + + partial doc update + +2001-09-15 04:14 jao + + * doc/mdk_gstart.texi: + + partial doc update + +2001-09-15 04:12 jao + + * mixguile/mixguile-commands.scm: + + all commands implemented in terms of mixvm-cmd to allow hook calling + +2001-09-14 02:48 jao + + * doc/mdk_ack.texi: + + typo + +2001-09-14 02:41 jao + + * doc/mdk_gstart.texi: + + doc update for version 0.5 + +2001-09-14 02:08 jao + + * mixguile/mixguile-commands.scm: + + (mix-pmem) no accepts two arguments (from, to) + +2001-09-13 02:13 jao + + * doc/: mdk.texi, mdk_bugs.texi, mdk_copying.texi, mdk_emixvm.texi, + mdk_findex.texi, mdk_gmixvm.texi, mdk_gstart.texi, mdk_index.texi, + mdk_install.texi, mdk_intro.texi, mdk_mixasm.texi, mdk_mixvm.texi, + mdk_tut.texi: + + partial doc update for version 0.5 + +2001-09-13 01:14 jao + + * mixlib/xmix_vm_handlers.c: + + add a newline character to the output of psrc and pprog + +2001-09-12 01:31 jao + + * doc/mdk_ack.texi: + + initial version (from the THANKS file) + +2001-09-12 01:20 jao + + * THANKS: + + Vasilij contribution + +2001-09-12 01:18 jao + + * THANKS: + + Radu Butnaru + +2001-09-12 00:53 jao + + * mixlib/mix_vm_clock.c: + + (mix_vm_clock_add_lapse) fixed time del for the MOVE instruction + +2001-09-11 01:42 jao + + * doc/mdk_intro.texi: + + version 0.5 update + +2001-09-10 22:35 jao + + * doc/mdk_gmixvm.texi: + + version 0.5 update + +2001-09-05 00:14 jao + + * doc/img/.cvsignore: + + ignore eps files + +2001-09-05 00:13 jao + + * doc/Makefile.am: + + licenses in one appendix + +2001-09-05 00:09 jao + + * doc/: .cvsignore, fdl.texi, gpl.texi, mdk.texi, mdk_copying.texi, + mdk_gmixvm.texi, mdk_index.texi: + + licenses in one appendix + +2001-09-04 04:36 jao + + * mixguile/mixguile-vm-stat.scm: + + using Id tag + +2001-09-04 04:35 jao + + * mixguile/mixguile-vm-stat.scm: + + vm status guile commands + +2001-09-04 04:31 jao + + * doc/Makefile.am: + + copyright notice updated + +2001-09-04 04:30 jao + + * doc/Makefile.am: + + fdl.texi file added + +2001-09-04 04:30 jao + + * doc/img/Makefile.am: + + missing files added + +2001-09-02 02:49 jao + + * mixguile/xmixguile_cmd_dispatcher.c: + + new procedures mix-src-line, mix-src-line-no + +2001-09-01 02:22 jao + + * mixguile/: mixguile-commands.scm, mixguile_cmd_dispatcher.c, + mixguile_cmd_dispatcher.h, xmixguile_cmd_dispatcher.c, + xmixguile_cmd_dispatcher.h: + + new mixguile commands + +2001-09-01 02:21 jao + + * mixguile/.cvsignore: + + more ignored files + +2001-09-01 02:21 jao + + * mixgtk/mixgtk_device.c: + + use of new command pddir + +2001-09-01 02:19 jao + + * mixutils/.cvsignore, mixutils/mixvm_command.c, + mixlib/mix_vm_command.c, mixlib/mix_vm_command.h, + mixlib/xmix_vm_command.c, mixlib/xmix_vm_command.h, + mixlib/xmix_vm_handlers.c, mixlib/xmix_vm_handlers.h: + + new commands: pddir, sddir, ptime, psrc, pprog, pline + +2001-09-01 02:16 jao + + * mixguile/mixguile.c: + + using access to check for bootstrap files + +2001-09-01 02:04 jao + + * mixgtk/mixgtk_widgets.c: + + using access to check for glade file + +2001-08-29 04:14 jao + + * mixguile/xmixguile_cmd_dispatcher.c, mixlib/mix_vm_command.c, + mixlib/mix_vm_command.h: + + new mix-guile commands + +2001-08-28 18:41 jao + + * mixguile/.cvsignore: + + more ignored files + +2001-08-28 18:38 jao + + * NEWS, configure.in, mixgtk/Makefile.am, mixgtk/gmixvm.c, + mixgtk/mixgtk_cmd_dispatcher.c, mixgtk/mixgtk_mixvm.c, + mixguile/Makefile.am, mixguile/mixguile.c, mixguile/mixguile.h, + mixguile/mixguile_cmd_dispatcher.c, mixguile/mixguile_main.c, + mixguile/xmixguile_cmd_dispatcher.c, mixlib/Makefile.am, + mixlib/mix_config.c, mixlib/mix_config.h, mixlib/mix_vm_command.c, + mixlib/mix_vm_command.h, mixlib/xmix_vm_command.c, + mixlib/xmix_vm_command.h, mixlib/xmix_vm_handlers.c, + mixlib/xmix_vm_handlers.h, mixutils/Makefile.am, mixutils/mixvm.c, + mixutils/mixvm_command.c, mixutils/mixvm_command.h, + mixutils/mixvm_loop.c, po/ChangeLog, .cvsignore: + + guile integration + +2001-08-23 02:01 jao + + * configure.in, mixgtk/Makefile.am, mixguile/Makefile.am, + mixguile/mixguile_main.c, mixutils/Makefile.am, po/ChangeLog, + mixguile/.cvsignore, mixguile/mixguile-commands.scm, + mixguile/mixguile.scm: + + mixguile commands + +2001-08-23 01:45 jao + + * mixutils/mixguile.c: + + file moved to mixguile dir + +2001-08-22 04:43 jao + + * mixguile/xmixguile_cmd_dispatcher.c: + + more commands + +2001-08-22 02:44 jao + + * mixutils/.cvsignore: + + more ignored files + +2001-08-22 02:42 jao + + * mixguile/Makefile.am, mixguile/mixguile.c, mixguile/mixguile.h, + mixguile/mixguile_cmd_dispatcher.c, + mixguile/mixguile_cmd_dispatcher.h, + mixguile/xmixguile_cmd_dispatcher.c, + mixguile/xmixguile_cmd_dispatcher.h, mixlib/mix_vm_command.c, + mixlib/mix_vm_command.h, mixutils/Makefile.am, mixutils/mixguile.c: + + mixguile: first version + +2001-08-21 02:31 jao + + * mixguile/.cvsignore: + + ignored files + +2001-08-21 02:30 jao + + * Makefile.am, configure.in, mixguile/Makefile.am, + mixguile/mixguile.c, mixguile/mixguile.h, + mixguile/mixguile_cmd_dispatcher.c, + mixguile/mixguile_cmd_dispatcher.h: + + initial guile support + +2001-08-20 02:42 jao + + * mixlib/mix_vm_command.c: + + memory leak fixed + +2001-08-20 02:36 jao + + * mixgtk/: mixgtk_fontsel.c, mixgtk_mixvm.c: + + memory leak fixed + +2001-08-17 04:32 jao + + * ChangeLog, NEWS: + + version 0.4.2 + +2001-08-17 04:26 jao + + * NEWS, mdk.spec, doc/img/ss_devices.jpg, doc/img/ss_mix.jpg, + doc/img/ss_mixal.jpg, doc/img/ss_split.jpg: + + version 0.4.2 + +2001-08-17 03:54 jao + + * mixgtk/mixgtk_device.c: + + devices destruction fixed + +2001-08-17 03:05 jao + + * ChangeLog, NEWS: + + version 0.4.2 + +2001-08-17 02:07 jao + + * mixgtk/Makefile.am: + + data files always included in distribution + +2001-08-17 02:06 jao + + * mixgtk/: Makefile.am, devdir.xpm, extern.xpm, mixgtk.glade: + + new toolbar buttons + +2001-08-17 01:08 jao + + * mixgtk/mixgtk.glade: + + MIXAL status bar + +2001-08-17 01:06 jao + + * mixgtk/mixgtk_mixal.c: + + display symbol values in MIXAL status bar when split + +2001-08-17 00:38 jao + + * aclocal.m4, configure.in: + + version 0.4.2 + +2001-08-17 00:37 jao + + * po/ChangeLog: + + new gettext version + +2001-08-17 00:32 jao + + * NEWS, mixgtk/.cvsignore, mixgtk/Makefile.am: + + toolbars added + +2001-08-17 00:28 jao + + * mixgtk/: clear.xpm, colors.xpm, compile.xpm, edit.xpm, font.xpm, + fontl.xpm, jump.xpm, mixgtk.glade, mixgtk_config.c, + mixgtk_config.h, mixgtk_wm.c, mixgtk_wm.h, next.xpm, onew.xpm, + open.xpm, output.xpm, run.xpm, splitw.xpm, symbols.xpm: + + toolbars added + +2001-07-26 00:00 jao + + * aclocal.m4, configure.in, mixutils/mixvm_command.c, po/ChangeLog: + + rl_completion_matches check + +2001-07-22 23:30 jao + + * mixgtk/mixgtk_mixal.c: + + release 0.4 + +2001-07-22 23:11 jao + + * NEWS: + + version 0.4 + +2001-07-22 23:08 jao + + * NEWS, doc/mdk_gstart.texi, doc/mdk_mixvm.texi, mixlib/mix_vm.c, + mixlib/mix_vm.h, mixlib/mix_vm_command.c, mixlib/mix_vm_command.h, + samples/.cvsignore, samples/bt.mixal, samples/cbp.mixal: + + version 0.4 + +2001-07-22 15:47 jao + + * mixlib/: mix_vm_command.c, xmix_vm.h: + + release 0.4 + +2001-07-22 01:02 jao + + * ChangeLog, mdk.spec: + + version 0.4 + +2001-07-22 00:54 jao + + * mixlib/: mix_predicate.c, mix_predicate_list.c, + mix_predicate_list.h, mix_vm.c, mix_vm.h, mix_vm_command.c: + + conditional breakpoints finished + +2001-07-22 00:09 jao + + * doc/: mdk_gstart.texi, mdk_mixvm.texi: + + conditional breakpoints + +2001-07-21 23:21 jao + + * NEWS: + + conditional breakpoints + +2001-07-21 23:14 jao + + * mixlib/mix_vm_command.c, mixlib/mix_vm_command.h, + mixutils/mixvm_command.c, samples/.cvsignore, samples/cbp.mixal: + + mem and register conditional breakpoints + +2001-07-21 23:11 jao + + * aclocal.m4: + + new macros + +2001-07-19 02:24 jao + + * mixlib/Makefile.am, mixlib/mix_config.c, mixlib/mix_predicate.c, + mixlib/mix_predicate.h, mixlib/mix_predicate_list.c, + mixlib/mix_predicate_list.h, mixlib/mix_vm.c, mixlib/mix_vm.h, + mixlib/mix_vm_command.c, mixlib/xmix_vm.h, mixutils/mixvm_loop.c, + po/ChangeLog: + + cond bp support + +2001-07-13 22:17 jao + + * doc/: mdk_gmixvm.texi, mdk_gstart.texi, img/ss_devdir.jpg, + img/ss_split.jpg: + + version 0.4 + +2001-07-11 01:04 jao + + * doc/: .cvsignore, mdk.texi, mdk_mixvm.texi: + + version 0.4 + +2001-07-10 00:55 jao + + * configure.in: + + version 0.4 + +2001-07-10 00:49 jao + + * NEWS, mixgtk/mixgtk.c, mixgtk/mixgtk_cmd_dispatcher.c, + mixgtk/mixgtk_cmd_dispatcher.h, mixlib/mix_config.c, + mixlib/mix_config.h, mixlib/mix_vm_command.c, + mixutils/mixvm_loop.c: + + history file + +2001-07-08 23:55 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_device.c, + mixgtk/mixgtk_gen_handlers.c, mixgtk/mixgtk_gen_handlers.h, + mixgtk/mixgtk_widgets.c, mixgtk/mixgtk_widgets.h: + + devdir command via menu + +2001-07-08 02:18 jao + + * mixgtk/: mixgtk_cmd_dispatcher.c, mixgtk_config.c, + mixgtk_config.h, mixgtk_device.c: + + use of mix_config + +2001-07-08 01:34 jao + + * mixlib/mix_config.c, mixlib/mix_device.c, mixlib/mix_device.h, + mixlib/mix_vm_command.c, mixlib/mix_vm_command.h, mixutils/mixvm.c, + mixutils/mixvm_command.c, mixutils/mixvm_command.h, + mixutils/mixvm_loop.c: + + use of devdir command + +2001-07-08 00:57 jao + + * mixlib/mix_config.h: + + (mix_config_get_filename) new function + +2001-07-07 22:46 jao + + * mixlib/: mix_vm_command.c, mix_vm_command.h: + + timing command + +2001-07-07 22:31 jao + + * mixlib/mix_vm_command.c: + + trace->tracing + +2001-07-07 00:28 jao + + * mixlib/: mix_vm_command.c, mix_vm_command.h: + + (mix_vm_cmd_dispatcher_new_with_config) new constructor tron/troff + substituted by trace on|off + +2001-07-06 01:38 jao + + * mixlib/: mix_device.c, mix_device.h, xmix_device.c, + xmix_device.h: + + externally provided device files directory + +2001-07-06 01:37 jao + + * mixlib/mix_config.c: + + use mix_stat_dir + +2001-07-06 01:37 jao + + * mixlib/: mix.c, mix.h: + + (mix_stat_dir) new function + +2001-07-06 01:35 jao + + * mixgtk/: mixgtk.h, mixgtk_config.c, mixgtk_device.c: + + use of .mdk instead of .gmixvm + +2001-07-03 00:56 jao + + * mixgtk/mixgtk_config.c: + + use of mix_config_t + +2001-07-03 00:39 jao + + * mixlib/: mix_config.c, mix_config.h, Makefile.am: + + shared config handler + +2001-07-01 15:33 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_cmd_dispatcher.c, + mixgtk/mixgtk_device.c: + + split improved + +2001-06-30 21:35 jao + + * mixgtk/: mixgtk.c, mixgtk_cmd_dispatcher.c, mixgtk_device.c, + mixgtk_widgets.c, mixgtk_wm.c: + + split improved + +2001-06-28 00:50 jao + + * mixgtk/: mixgtk.c, mixgtk.glade, mixgtk.h, mixgtk_fontsel.c, + mixgtk_fontsel.h, mixgtk_mixal.c, mixgtk_mixvm.c, mixgtk_widgets.c, + mixgtk_widgets.h, mixgtk_wm.c: + + hot split swap + +2001-06-26 01:52 jao + + * mixgtk/: mixgtk.c, mixgtk.h, mixgtk_cmd_dispatcher.c, + mixgtk_colorsel.c, mixgtk_colorsel.h, mixgtk_device.c, + mixgtk_fontsel.c, mixgtk_gen_handlers.c, mixgtk_input.c, + mixgtk_input.h, mixgtk_mixal.c, mixgtk_widgets.c, mixgtk_wm.c: + + hot split/unsplit + +2001-06-24 18:58 jao + + * mixgtk/mixgtk.glade: + + split windows mode + +2001-06-24 18:56 jao + + * NEWS: + + display file in title + +2001-06-24 18:51 jao + + * mixgtk/mixgtk_cmd_dispatcher.c: + + display file in title + +2001-06-24 15:06 jao + + * mixgtk/: .cvsignore, Makefile.am, mixgtk.c, mixgtk.glade, + mixgtk_cmd_dispatcher.c, mixgtk_cmd_dispatcher.h, mixgtk_config.c, + mixgtk_config.h, mixgtk_fontsel.c, mixgtk_fontsel.h, + mixgtk_mixal.c, mixgtk_mixal.h, mixgtk_mixvm.c, mixgtk_mixvm.h, + mixgtk_widgets.c, mixgtk_widgets.h, mixgtk_wm.c, mixgtk_wm.h: + + split windows mode + +2001-06-23 10:05 jao + + * samples/.cvsignore: + + release 0.3.5 + +2001-06-22 04:16 jao + + * doc/img/Makefile.am, ChangeLog: + + version 0.3.5 + +2001-06-22 04:12 jao + + * README: + + url + +2001-06-21 23:13 jao + + * mixgtk/mixgtk.glade: + + release 0.3.5 + +2001-06-21 22:47 jao + + * mixgtk/mixgtk_mixal.c: + + release 0.3.5 + +2001-06-21 22:27 jao + + * mdk.spec, doc/mdk.texi, doc/mdk_gmixvm.texi, + doc/img/ss_colors.jpg, doc/img/ss_devform.jpg, + doc/img/ss_devices.jpg, doc/img/ss_extprog.jpg, + doc/img/ss_goto.jpg, doc/img/ss_mix.jpg, doc/img/ss_mixal.jpg, + doc/img/ss_symbols.jpg, doc/img/ss_worddlg.jpg, + mixgtk/mixgtk.glade, mdk.spec: + + release 0.3.5 + +2001-06-19 00:59 jao + + * NEWS: + + psym bugs fixed + +2001-06-19 00:54 jao + + * mixlib/mix_symbol_table.c: + + (add_symbol_) symbol value correctly recovered (including sign) + +2001-06-19 00:43 jao + + * mixlib/mix_vm_command.c: + + (cmd_psym_) symbols printed to the correct stream + +2001-06-19 00:27 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_mixal.c, + mixgtk/mixgtk_widgets.c, mixgtk/mixgtk_widgets.h: + + gmixvm symbols dialog + +2001-06-18 01:26 jao + + * mixgtk/mixgtk.glade: + + minor change + +2001-06-18 01:05 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_mixal.c: + + variables in status bar + +2001-06-15 23:09 jao + + * configure.in: + + version 0.3.5 + +2001-06-15 23:08 jao + + * NEWS: + + font config bug fixed + +2001-06-15 22:37 jao + + * mixgtk/mixgtk_fontsel.c: + + font config bug fixed + +2001-06-15 17:00 jao + + * mixgtk/: mixgtk_gen_handlers.c, mixgtk_gen_handlers.c: + + bug corrected + +2001-06-12 23:37 jao + + * doc/mdk.texi: + + version 0.3.4 + +2001-06-12 23:34 jao + + * NEWS: + + version 0.3.4 + +2001-06-12 23:28 jao + + * configure.in: + + version 0.3.4 + +2001-06-12 18:07 jao + + * mixgtk/mixgtk_device.c: + + segfault corrected + +2001-06-11 22:39 jao + + * THANKS: + + adrian + +2001-06-11 22:38 jao + + * THANKS: + + minor changes + +2001-06-10 14:45 jao + + * doc/mdk_gmixvm.texi: + + minor changes + +2001-06-10 14:15 jao + + * doc/mdk_gmixvm.texi: + + minor changes + +2001-06-10 00:49 jao + + * ChangeLog, mdk.spec, doc/.cvsignore, doc/img/.cvsignore: + + version 0.3.3 + +2001-06-09 16:38 jao + + * NEWS, mdk.spec, doc/mdk.texi, doc/mdk_gmixvm.texi, + doc/mdk_mixvm.texi, doc/img/.cvsignore, doc/img/Makefile.am, + doc/img/ss_devform.jpg, doc/img/ss_extprog.jpg: + + version 0.3.3 + +2001-06-09 00:58 jao + + * aclocal.m4: + + version 0.3.3 + +2001-06-09 00:31 jao + + * configure.in: + + version 0.3.3 + +2001-06-09 00:29 jao + + * NEWS: + + minor changes + +2001-06-09 00:27 jao + + * mixgtk/: mixgtk.glade, mixgtk_cmd_dispatcher.c, + mixgtk_cmd_dispatcher.h, mixgtk_gen_handlers.c, + mixgtk_gen_handlers.h: + + edit and compile menu entries added + +2001-06-09 00:26 jao + + * mixlib/: mix_vm_command.c, mix_vm_command.h: + + src file path accessor added + +2001-06-08 02:49 jao + + * THANKS: + + new guys + +2001-06-08 02:08 jao + + * doc/mdk_tut.texi: + + minor correction + +2001-06-07 00:49 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_cmd_dispatcher.c: + + command history and tab completion added + +2001-06-07 00:48 jao + + * mixutils/.cvsignore: + + new ignored file + +2001-06-05 23:26 jao + + * mixlib/mix_vm_command.c: + + (cmd_edit_) messages about executed command added + +2001-06-05 23:23 jao + + * mixlib/mix_vm_command.c: + + (cmd_compile_) messages about executed command added + +2001-06-05 23:17 jao + + * mixutils/mixvm_command.c: + + use of mix_vm_cmd_dispatcher edit and compile commands + +2001-06-05 23:04 jao + + * mixlib/mix_parser.c: + + copyright notice + +2001-06-05 23:03 jao + + * mixlib/mix_parser.c: + + the src path always correctly stored + +2001-06-05 23:02 jao + + * mixlib/: mix_vm_command.c, mix_vm_command.h: + + edit and compile commands added + +2001-06-05 22:15 jao + + * mixlib/: mix_vm_command.c, mix_vm_command.h: + + edit and compile commands added + +2001-06-05 00:13 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_cmd_dispatcher.c, + mixgtk/mixgtk_mixvm.h, mixgtk/mixgtk_widgets.c, + mixgtk/mixgtk_widgets.h, mixlib/mix_file.c, mixlib/mix_file.h, + samples/primes.mixal: + + edit and compile commands added to gmixvm + +2001-06-05 00:05 jao + + * mixlib/mix_vm_command.c: + + (mix_vm_cmd_dispatch) \n added to unknown command message + +2001-06-03 13:24 jao + + * mixgtk/mixgtk.glade: + + extern program dialog added + +2001-06-03 13:19 jao + + * mixgtk/.cvsignore, mixlib/.cvsignore, samples/.cvsignore: + + new ignored files + +2001-06-03 13:16 jao + + * NEWS: + + when a file is reloaded, breakpoints are no reset + +2001-06-03 13:06 jao + + * mixlib/mix_vm.c: + + (mix_vm_load_file) when a file is reloaded, breakpoints are no reset + +2001-06-03 11:04 jao + + * mixlib/mix_scanner.l: + + CON bug fixed + +2001-05-31 00:15 jao + + * NEWS, mixgtk/mixgtk.glade, mixgtk/mixgtk_device.c, + mixgtk/mixgtk_device.h, mixgtk/mixgtk_widgets.c, + mixgtk/mixgtk_widgets.h, mixlib/mix_vm.c, mixlib/mix_vm.h: + + binary devices output formats added + +2001-05-25 00:56 jao + + * doc/: fdl.texi, gpl.texi, mdk.texi, mdk_bugs.texi, + mdk_emixvm.texi, mdk_gmixvm.texi, mdk_gstart.texi, mdk_index.texi, + mdk_install.texi, mdk_intro.texi, mdk_mixasm.texi, mdk_mixvm.texi, + mdk_tut.texi: + + license changed to gfdl + +2001-05-24 02:38 jao + + * mixgtk/: mixgtk.c, mixgtk.glade, mixgtk.h, mixgtk_colorsel.c, + mixgtk_colorsel.h, mixgtk_fontsel.c, mixgtk_fontsel.h, + mixgtk_input.c, mixgtk_input.h, mixgtk_mixvm.c, mixgtk_widgets.c, + mixgtk_widgets.h: + + deferred dialog creation + +2001-05-19 20:53 jao + + * doc/img/ss_goto.jpg: + + 0.3.2 release + +2001-05-19 16:58 jao + + * Makefile.am, mdk.spec: + + file mdk.spec added to the distribution + +2001-05-19 16:55 jao + + * mixgtk/mixgtk_mixvm.c, doc/img/ss_colors.jpg, + doc/img/ss_devices.jpg, doc/img/ss_goto.jpg, doc/img/ss_mix.jpg, + doc/img/ss_mixal.jpg, doc/img/ss_worddlg.jpg: + + 0.3.2 release + +2001-05-16 23:09 jao + + * ChangeLog: + + 0.3.2 release + +2001-05-16 23:06 jao + + * samples/: stress5.mixal, stress6.mixal: + + 0.3.2 release + +2001-05-16 23:02 jao + + * INSTALL, samples/.cvsignore: + + 0.3.2 release + +2001-05-16 01:28 jao + + * doc/mdk_install.texi: + + CVS URL corrected + +2001-05-16 01:20 jao + + * doc/img/Makefile.am: + + new figures added + +2001-05-16 01:11 jao + + * ChangeLog: + + 0.3.2 release + +2001-05-16 01:08 jao + + * .cvsignore, configure.in, updatelog, doc/mdk.texi, + doc/mdk_gmixvm.texi, doc/mdk_install.texi, doc/img/ss_colors.jpg, + doc/img/ss_goto.jpg, mixlib/mix.h, samples/.cvsignore: + + 0.3.2 release + +2001-05-14 00:58 jao + + * THANKS, NEWS: + + name typo + +2001-05-14 00:54 jao + + * NEWS, THANKS: + + 0.3.2 release + +2001-05-11 00:10 jao + + * NEWS: + + 0.3.2 release + +2001-05-10 23:48 jao + + * mixgtk/: mixgtk.glade, mixgtk_device.c, mixgtk_fontsel.c: + + devices font customisation added + +2001-05-10 01:45 jao + + * mixlib/: mix_file.c, xmix_io.c: + + read/write files not truncated if they already exist + +2001-05-10 01:17 jao + + * mixgtk/mixgtk_device.c: + + minor changes + +2001-05-10 01:16 jao + + * mixlib/: mix_io.c, xmix_device.c, xmix_io.c: + + (mix_io_write_*_array) bug corrected + +2001-05-08 01:03 jao + + * mixgtk/mixgtk_device.c: + + use of virtual device destructor to delete devices after program + reload + +2001-05-08 01:02 jao + + * mixlib/: mix_device.c, mix_vm.c, xmix_device.c, xmix_device.h: + + mix_device_t: virtual destructor added + +2001-05-06 23:38 jao + + * mixgtk/mixgtk_device.c, mixlib/mix_device.c, + mixlib/xmix_device.c, mixlib/xmix_device.h: + + support for gtk binary devices added + +2001-05-04 01:48 jao + + * mixlib/: mix_vm.c, mix_vm.h, xmix_vm.c, xmix_vm.h: + + new devices are created by a (possibly externally provided) factory + +2001-05-04 01:35 jao + + * mixgtk/mixgtk_fontsel.c: + + (change_font_) setting current font on fontsel dialog when available + +2001-05-04 01:34 jao + + * mixgtk/mixgtk.c: + + (mixgtk_init) check for the existence of glade xml file(s) before + using it + +2001-04-30 01:28 jao + + * mixgtk/mixgtk.glade: + + minor changes + +2001-04-29 22:40 jao + + * mixgtk/: mixgtk_fontsel.c, mixgtk_mixal.c: + + config file handling added + +2001-04-29 14:56 jao + + * mixgtk/: Makefile.am, mixgtk.c, mixgtk.glade, mixgtk.h, + mixgtk_config.c, mixgtk_config.h, mixgtk_fontsel.c, + mixgtk_gen_handlers.c, mixgtk_gen_handlers.h, mixgtk_widgets.c: + + config file handling added + +2001-04-28 22:54 jao + + * mixgtk/: Makefile.am, gmixvm.c, mixgtk.c, mixgtk.h: + + initialisation, clean-up and main functionality split + +2001-04-28 00:54 jao + + * mixgtk/: .cvsignore, Makefile.am, mixgtk.c, mixgtk.glade, + mixgtk_fontsel.c, mixgtk_fontsel.h, mixgtk_widgets.c, + mixgtk_widgets.h: + + font customization added + +2001-04-23 23:30 jao + + * mixutils/Makefile.am: + + intlibs recovered + +2001-04-22 22:07 jao + + * mixlib/mix_vm_command.c: + + (cmd_pmem_) seg fault when freeing (changed) arg valued corrected + +2001-04-22 02:04 jao + + * mixgtk/: Makefile.am, mixgtk.c, mixgtk.glade, mixgtk_colorsel.c, + mixgtk_colorsel.h, mixgtk_mixal.c, mixgtk_mixal.h, + mixgtk_widgets.c, mixgtk_widgets.h: + + color custumozation added + +2001-04-21 23:59 jao + + * doc/mdk_install.texi: + + minor changes + +2001-04-21 23:30 jao + + * mixgtk/mixgtk_mixal.c: + + (on_mixal_select_row) set/unset breakpoints on location line + +2001-04-09 01:15 jao + + * INSTALL: + + release 0.3.1 + +2001-04-09 00:40 jao + + * .cvsignore: + + ignored files + +2001-04-09 00:40 jao + + * doc/mdk.texi, doc/mdk_install.texi, ChangeLog: + + release 0.3.1 + +2001-04-09 00:19 jao + + * aclocal.m4, NEWS: + + release 0.3.1 + +2001-04-08 22:35 jao + + * aclocal.m4, configure.in: + + gtk test recovered + +2001-04-08 22:23 jao + + * NEWS, THANKS, mixgtk/mixgtk_cmd_dispatcher.c: + + compilation on FreeBSD fixed + +2001-04-08 00:13 jao + + * lib/.cvsignore, samples/.cvsignore: + + ignored files + +2001-04-08 00:12 jao + + * Makefile.am, aclocal.m4, configure.in, lib/Makefile.am, + lib/getopt.h, lib/getopt_long.c, mixgtk/Makefile.am, + mixutils/Makefile.am, mixutils/mixasm.c, mixutils/mixvm.c: + + getopt and getopt_long provided if missing + +2001-04-07 12:23 jao + + * mixlib/mix_file.h: + + minor changes + +2001-04-03 00:19 jao + + * mixutils/mixvm_loop.c: + + use of gets avoided for FreeBSD portability + +2001-04-03 00:11 jao + + * mixgtk/mixgtk_device.c: + + use of opem_memstream avoided for FreeBSD portability + +2001-04-02 21:32 jao + + * misc/Makefile.am: + + mixvm.el installed as package data + +2001-04-01 15:23 jao + + * mixgtk/: mixgtk_cmd_dispatcher.c, mixgtk_mixal.c, mixgtk_input.c: + + including prototype for strlen (string.h) + +2001-04-01 15:22 jao + + * mixlib/mix_vm_command.c: + + (cmd_smem_) variables always initialised + +2001-04-01 15:09 jao + + * mixlib/: mix_eval_scanner.l, mix_scanner.l: + + including prototype for strlen (string.h) + +2001-04-01 15:06 jao + + * mixlib/: mix_code_file.c, mix_parser.c: + + including prototype for strlen (string.h) + +2001-04-01 15:04 jao + + * mixlib/mix_file.c: + + including prototype for strlen and strcmp (string.h) + +2001-04-01 15:01 jao + + * mixlib/mix_symbol_table.c: + + including prototype for strlen (string.h) + +2001-04-01 14:59 jao + + * mixlib/xmix_vm.h: + + including prototype for memset (string.h) + +2001-04-01 00:04 jao + + * configure.in, doc/mdk.texi, mixgtk/mixgtk_mixal.h: + + minor changes + +2001-03-31 02:35 jao + + * doc/mdk.texi: + + direntry added + +2001-03-30 23:09 jao + + * doc/Makefile.am: + + missing file + +2001-03-30 02:23 jao + + * mixgtk/Makefile.am, mixutils/Makefile.am: + + included gettext libs properly used when specified in configuration + +2001-03-28 01:20 jao + + * TODO: + + release 0.3 + +2001-03-28 01:16 jao + + * THANKS, NEWS: + + release 0.3 + +2001-03-28 01:12 jao + + * .cvsignore, NEWS, configure.in, doc/Makefile.am, doc/mdk.texi, + doc/mdk_gmixvm.texi, doc/ss_devices.png, doc/ss_mix.png, + doc/ss_mix.txt, doc/ss_mixal.png, doc/ss_mixal.txt, + doc/ss_worddlg.png, doc/img/.cvsignore, doc/img/Makefile.am, + samples/stress2.mixal: + + 0.3 release + +2001-03-26 00:54 jao + + * doc/img/: ss_devices.jpg, ss_devices.png, ss_mix.jpg, ss_mix.png, + ss_mixal.jpg, ss_mixal.png, ss_worddlg.jpg, ss_worddlg.png: + + images translated to jpg + +2001-03-26 00:45 jao + + * doc/img/: Makefile.am, ss_devices.png, ss_mix.png, ss_mix.txt, + ss_mixal.png, ss_mixal.txt, ss_worddlg.png, ss_mixal.txt: + + doc images + +2001-03-26 00:06 jao + + * doc/ss_mixal.txt: + + info mode figure + +2001-03-22 04:01 jao + + * .cvsignore, AUTHORS, COPYING, ChangeLog, INSTALL, Makefile.am, + NEWS, README, THANKS, TODO, acconfig.h, aclocal.m4, autogen.sh, + configure.in, doc/.cvsignore, doc/Makefile.am, doc/gpl.texi, + doc/mdk.texi, doc/mdk_bugs.texi, doc/mdk_emixvm.texi, + doc/mdk_gmixvm.texi, doc/mdk_gstart.texi, doc/mdk_index.texi, + doc/mdk_install.texi, doc/mdk_intro.texi, doc/mdk_mixasm.texi, + doc/mdk_mixvm.texi, doc/mdk_tut.texi, doc/ss_devices.png, + doc/ss_mix.png, doc/ss_mix.txt, doc/ss_mixal.png, + doc/ss_worddlg.png, misc/.cvsignore, misc/Makefile.am, + misc/mixvm.el, mixgtk/.cvsignore, mixgtk/Makefile.am, + mixgtk/mixgtk.c, mixgtk/mixgtk.glade, + mixgtk/mixgtk_cmd_dispatcher.c, mixgtk/mixgtk_cmd_dispatcher.h, + mixgtk/mixgtk_device.c, mixgtk/mixgtk_device.h, + mixgtk/mixgtk_gen_handlers.c, mixgtk/mixgtk_gen_handlers.h, + mixgtk/mixgtk_input.c, mixgtk/mixgtk_input.h, + mixgtk/mixgtk_mixal.c, mixgtk/mixgtk_mixal.h, + mixgtk/mixgtk_mixvm.c, mixgtk/mixgtk_mixvm.h, + mixgtk/mixgtk_widgets.c, mixgtk/mixgtk_widgets.h, + mixlib/.cvsignore, mixlib/Makefile.am, mixlib/mix.c, mixlib/mix.h, + mixlib/mix_code_file.c, mixlib/mix_code_file.h, + mixlib/mix_device.c, mixlib/mix_device.h, mixlib/mix_eval.c, + mixlib/mix_eval.h, mixlib/mix_eval_scanner.l, mixlib/mix_file.c, + mixlib/mix_file.h, mixlib/mix_ins.c, mixlib/mix_ins.h, + mixlib/mix_io.c, mixlib/mix_io.h, mixlib/mix_parser.c, + mixlib/mix_parser.h, mixlib/mix_scanner.l, mixlib/mix_src_file.c, + mixlib/mix_src_file.h, mixlib/mix_symbol_table.c, + mixlib/mix_symbol_table.h, mixlib/mix_types.c, mixlib/mix_types.h, + mixlib/mix_vm.c, mixlib/mix_vm.h, mixlib/mix_vm_clock.c, + mixlib/mix_vm_clock.h, mixlib/mix_vm_command.c, + mixlib/mix_vm_command.h, mixlib/mix_vm_dump.c, + mixlib/mix_vm_dump.h, mixlib/xmix_device.c, mixlib/xmix_device.h, + mixlib/xmix_eval.h, mixlib/xmix_io.c, mixlib/xmix_io.h, + mixlib/xmix_parser.h, mixlib/xmix_vm.c, mixlib/xmix_vm.h, + mixlib/testsuite/.cvsignore, mixlib/testsuite/Makefile.am, + mixlib/testsuite/mix_device_t.c, mixlib/testsuite/mix_eval_t.c, + mixlib/testsuite/mix_ins_t.c, mixlib/testsuite/mix_parser_t.c, + mixlib/testsuite/mix_types_t.c, mixlib/testsuite/mix_vm_ins_t.c, + mixlib/testsuite/test.h, mixutils/.cvsignore, mixutils/Makefile.am, + mixutils/mixasm.c, mixutils/mixasm_comp.c, mixutils/mixasm_comp.h, + mixutils/mixvm.c, mixutils/mixvm_command.c, + mixutils/mixvm_command.h, mixutils/mixvm_loop.c, po/.cvsignore, + po/ChangeLog, po/POTFILES.in, samples/.cvsignore, + samples/Makefile.am, samples/hello.mixal, samples/primes.mixal, + samples/primes.result, samples/stress1.mixal, + samples/stress2.mixal, samples/stress4.mixal: + + Initial revision + +2001-03-22 04:01 jao + + * .cvsignore, AUTHORS, COPYING, ChangeLog, INSTALL, Makefile.am, + NEWS, README, THANKS, TODO, acconfig.h, aclocal.m4, autogen.sh, + configure.in, doc/.cvsignore, doc/Makefile.am, doc/gpl.texi, + doc/mdk.texi, doc/mdk_bugs.texi, doc/mdk_emixvm.texi, + doc/mdk_gmixvm.texi, doc/mdk_gstart.texi, doc/mdk_index.texi, + doc/mdk_install.texi, doc/mdk_intro.texi, doc/mdk_mixasm.texi, + doc/mdk_mixvm.texi, doc/mdk_tut.texi, doc/ss_devices.png, + doc/ss_mix.png, doc/ss_mix.txt, doc/ss_mixal.png, + doc/ss_worddlg.png, misc/.cvsignore, misc/Makefile.am, + misc/mixvm.el, mixgtk/.cvsignore, mixgtk/Makefile.am, + mixgtk/mixgtk.c, mixgtk/mixgtk.glade, + mixgtk/mixgtk_cmd_dispatcher.c, mixgtk/mixgtk_cmd_dispatcher.h, + mixgtk/mixgtk_device.c, mixgtk/mixgtk_device.h, + mixgtk/mixgtk_gen_handlers.c, mixgtk/mixgtk_gen_handlers.h, + mixgtk/mixgtk_input.c, mixgtk/mixgtk_input.h, + mixgtk/mixgtk_mixal.c, mixgtk/mixgtk_mixal.h, + mixgtk/mixgtk_mixvm.c, mixgtk/mixgtk_mixvm.h, + mixgtk/mixgtk_widgets.c, mixgtk/mixgtk_widgets.h, + mixlib/.cvsignore, mixlib/Makefile.am, mixlib/mix.c, mixlib/mix.h, + mixlib/mix_code_file.c, mixlib/mix_code_file.h, + mixlib/mix_device.c, mixlib/mix_device.h, mixlib/mix_eval.c, + mixlib/mix_eval.h, mixlib/mix_eval_scanner.l, mixlib/mix_file.c, + mixlib/mix_file.h, mixlib/mix_ins.c, mixlib/mix_ins.h, + mixlib/mix_io.c, mixlib/mix_io.h, mixlib/mix_parser.c, + mixlib/mix_parser.h, mixlib/mix_scanner.l, mixlib/mix_src_file.c, + mixlib/mix_src_file.h, mixlib/mix_symbol_table.c, + mixlib/mix_symbol_table.h, mixlib/mix_types.c, mixlib/mix_types.h, + mixlib/mix_vm.c, mixlib/mix_vm.h, mixlib/mix_vm_clock.c, + mixlib/mix_vm_clock.h, mixlib/mix_vm_command.c, + mixlib/mix_vm_command.h, mixlib/mix_vm_dump.c, + mixlib/mix_vm_dump.h, mixlib/xmix_device.c, mixlib/xmix_device.h, + mixlib/xmix_eval.h, mixlib/xmix_io.c, mixlib/xmix_io.h, + mixlib/xmix_parser.h, mixlib/xmix_vm.c, mixlib/xmix_vm.h, + mixlib/testsuite/.cvsignore, mixlib/testsuite/Makefile.am, + mixlib/testsuite/mix_device_t.c, mixlib/testsuite/mix_eval_t.c, + mixlib/testsuite/mix_ins_t.c, mixlib/testsuite/mix_parser_t.c, + mixlib/testsuite/mix_types_t.c, mixlib/testsuite/mix_vm_ins_t.c, + mixlib/testsuite/test.h, mixutils/.cvsignore, mixutils/Makefile.am, + mixutils/mixasm.c, mixutils/mixasm_comp.c, mixutils/mixasm_comp.h, + mixutils/mixvm.c, mixutils/mixvm_command.c, + mixutils/mixvm_command.h, mixutils/mixvm_loop.c, po/.cvsignore, + po/ChangeLog, po/POTFILES.in, samples/.cvsignore, + samples/Makefile.am, samples/hello.mixal, samples/primes.mixal, + samples/primes.result, samples/stress1.mixal, + samples/stress2.mixal, samples/stress4.mixal: + + initial import (sf 0.3beta) + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..4a960d7 --- /dev/null +++ b/INSTALL @@ -0,0 +1,339 @@ +Installing MDK +************** + +Download the source tarball +=========================== + + GNU MDK is distributed as a source tarball available for download in +the following URLs: + + * (or one of its mirrors + (http://www.gnu.org/prep/ftp.html)) + + * `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: + + * `https://savannah.gnu.org/cvs/?group_id=118' + + 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.1). + +Requirements +============ + + In order to build and install MDK, you will need the following +libraries installed in your system: + + - GLIB 2.4.0 (http://www.gtk.org) (required) + + - GNU Flex 2.5 (http://www.gnu.org/software/flex/flex.html) + (required) + + - GTK 2.4.0 (http://www.gtk.org) (optional) + + - Libglade 2.4.0 (http://ftp.gnome.org/pub/GNOME/sources/libglade/2.4/) + (optional) + + - GNU Readline + (http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html) + (optional) + + - GNU Libguile 1.6 (http://www.gnu.org/software/guile) (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'. Finally, +if libguile is found, the MDK utilities will be compiled with Guile +support and will be extensible using Scheme. + + *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 `libgtk2.0' and +`libgtk2.0-dev' on Debian). + +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 1.2.1 has been successfully configured. *** + + Type 'make' to build the following utilities: + - mixasm (MIX assembler) + - mixvm (MIX virtual machine, with readline support, + with guile support) + - gmixvm (mixvm GTK+ GUI, with guile support) + - mixguile (the mixvm guile shell) + +where the last lines 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' + + - `mixguile/mixguile' + + 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. + +Emacs support +============= + + `mixvm' can be run within an Emacs GUD buffer using the elisp +program `misc/mixvm.el', kindly contributed by {No value for `PHILIP'}. + + `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) + +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 build of the MIX virtual machine GUI + (`gmixvm'). If the required libraries are missing (*note + Requirements::) the configure script with automatically disable + this feature. + + - User Option: -with-guile[=yes|no] + - User Option: -without-guile + Enables/disables the Guile support for `mixvm' and `gmixvm', and + the build of `mixguile'. If the required libraries are missing + (*note 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 (*note Requirements::) the configure + script with automatically disable this feature. + + For additional, boilerplate configure options, see the + `Generic configure help' below, or run + + configure --help + +------------------------------------------------------------------------ +------------------------------------------------------------------------ + +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. + +---- + +$Id: INSTALL,v 1.7 2005/09/20 20:18:58 jao Exp $ diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..cfd46d1 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,24 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2000, 2001, 2004 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 = config.rpath ABOUT-NLS intltool-extract.in intltool-merge.in \ + intltool-update.in +SUBDIRS = po intl doc lib mixlib mixguile mixutils mixgtk misc samples + +distclean-local: + rm -f intltool-extract + rm -f intltool-merge + rm -f intltool-update + +docdir = $(top_builddir)/doc + +ACLOCAL_AMFLAGS = -I m4 diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..5aee4ec --- /dev/null +++ b/NEWS @@ -0,0 +1,450 @@ +GNU MDK -- History of visible changes. + +Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, Free Software Foundation, Inc. +See the end for copying conditions. + +Please send mdk bug reports to bug-mdk@gnu.org. + +--------------------------------------------------------------------------- +* Version 1.2.1 (20/09/05) + +** MIXAL compliance improvements (Sergey Poznyakoff): + + - w-expressions in literals are now admitted (e.g. LDA =8(1:1)=) + - ALF now accepts non-quoted arguments (in addition to quoted + - ones), as in the original TAOCP definition. + +** German translation updated (thanks to Jens Seidel) + +** mixal.el improvements (Pieter Pareit) + +** Bug fixes: + + - gmixvm's failure to dynamically link with libglade (#13661) + (thanks to Sascha Wilde) + - mixal.el calls mixasm with obsolete -g option (#14569) (thanks to + Sascha Wilde) + - mixasm -g causes a coredump (#14579) (Pieter Pareit) + +--------------------------------------------------------------------------- +* Version 1.2 (05/08/04) + +** Graphical user interface (gmixvm) updated to gtk+ 2.4.x + + - gmixvm now uses the latest version of the gtk+ toolkit, including + antialiased Pango fonts. + - Individually detachable windows for the virtual machine, the + source window and the devices notebook (there is no 'split mode' + anymore). + - Detachable toolbars. + - Current source line and breakpoints are now marked via icons. + - New menu option to change all fonts at once. + +** German i18n available (thanks to Mike Scholz). Set LANG to + de_DE.UTF-8 to use it. + +** mixasm includes debug info in compiled mix files by default: the + options -g and --debug are gone; if you want to compile without + debug info, use -O or --ndebug. + +--------------------------------------------------------------------------- +* Version 1.1 (12/06/04) + +** The typewriter device (19) is now input/output, so that you can + read characters from standard input (mixvm) or a popup dialog + (gmixvm) in your MIXAL programs (see samples/echo.mixal for a + simple usage sample). + +** Input character device files may now contain lines with less than the + required block size; the virtual machine pads the missing + characters in memory using 0 (MIX char 'space'). + +** The paper tape device (20) was incorrectly defined as an output + device. It is now an input char device (cf. TAOCP vol.1 p. 133, + where it is mentioned as the 'paper tape reader'; thanks to Michael + Talbot-Wilson). + +** Listings produced by mixasm improved: better layout, and correct + identification of 'ALF' and 'CON' instructions (including those + added by the compiler as a result of local constant definitions and + future references. + +** Local constants can now be modified by a field spec or an index, + as in, say, CMPA =0=,1(3:2) (closes #5654). + +** The virtual machine reader is now case-insensitive, i.e., it + automatically converts lowercase characters in input char device + files to their uppercase counterparts (which are the only ones + admitted by MIX). The ASCII representation for MIX chars delta, + sigma and pi is now ~, [ and #. + +** Bug fix: mixvm prompt's ending whitespace is now correctly set. + +** Bug fix: blocks in input char devices (e.g. the card reader) are + now expected to be separated by newlines, mirroring char output, + which is done so (i.e. with one ASCII line per block). + +** Improved virtual machine error messages (bad memory address, device + no., fspec, etc.). + +** Bug fix: undefined symbols are transformed to new addresses just + before the end of a compiled program (as per TAOCP v1 p. 156; + thanks to WeiZeng). + +** Bug fix: the vm no longer blows up on memory access violations + (thanks to Joel R. Holveck; closes #5649). + +** Bug fix: LDAN, LDXN and LDiN always negate the result, even if zero + (thanks to Ruslan Batdalov; closes Debian's #247392). + +--------------------------------------------------------------------------- +* Version 1.0.1 (09/06/03) + +** New misc/mixal-mode.el for emacs (and associated docs), written by + Pieter Pareit. + +** Error message for unquoted ALF operand improved. + +** Fixed bug that caused (g)mixvm to segfault when reading a false MIX + file. + +** All translatable strings are ready for i18n. + +** Portability fixes to extend supported platforms. + +** When the program counter reaches address 4000 during program + execution, it is set back to its maximum value, 3999, and the + program halts, to avoid infinite loops. + +** Minor documentation improvements. + +** Minor bug fixes. + +--------------------------------------------------------------------------- +* Version 1.0 (08/04/02) + +** The stable release. + +** New command line option added to 'mixvm': -t (--time) to turn on + virtual execution time printing (it is now off by default). + +** New 'mixvm' command: prompt, lets you change the mixvm command + prompt ("MIX > " by default). + +** When the program counter reaches address 4000 during program + execution, it wraps up to value 0, to keep always a valid + address. Caveat: a program missing the HLT instruction can loop + indefinitely. + +** New supported platform: Mac OS X. + +** User manual reviewed and updated. + +** Bug fix: 'configure' libraries detection now works properly. + +** Bug fix: missing #includes added to avoid compilation errors in + some platforms (RedHat 7.1, ia64 with gcc 3.0). + +--------------------------------------------------------------------------- +* Version 0.5 (29/09/01) + +** Added Guile support: + - New utility 'mixguile': a Guile shell with an embedded MIX + virtual machine. + - gmixvm and mixvm have an embedded Guile interpreter: Scheme + can be used as an extension language. + - See the updated User's Manual for details. + +** New (g)mixvm commands: + - psrc: print the current program's source file path + - pprog: print the current program's path + - pline: print the current program line + - pstat: print the current virtual machine status + - slog: set on/off the logging of info messages to stdout (or + the command log in gmixvm) + +** For the sake of coherence, the following (g)mixvm commands + have been renamed: + - tracing -> strace + - timing -> stime (set on/off timing), + ptime (print timing stats) + - devdir -> sddir (set the devices dir), + pddir (print the devices dir) + +** Major documentation update to include Guile support and various + cosmetic corrections for pretty ps and pdf manuals (provided in the + distribution in addition to the html format). + +** In gmixvm, when a font specified in the config file cannot be + loaded, it is removed from the configuration. + +** gmixvm now accepts the standard command line options -vuh + +** Bug fix: when the MIX font is changed in gmixvm, the loc widget + font is correctly updated. + +** Bug fix: help messages are now correctly aligned in (g)mixvm. + +** Bug fix: timing statitics for the MOVE instruction are correctly + computed. + +** Bug fix: pressing return at an empty 'MIX >' prompt does not + produce an error message. + +** Bug fix: the configure script now correctly detects the absence of + libglade (needed by gmixvm). + +** Bug fix: makefiles corrected so that mdk accepts a VPATH build + ('make distcheck' works now) + +--------------------------------------------------------------------------- +* Version 0.4.2 (17/08/01) + +** New toolbars for gmixvm windows. + +** Toolbars can be hidden, using View->Toolbar checkbox. + +** New icon for the "goto loc pointer address" button. + +** The menu entry "Split windows" has been moved from "Settings" to + "View" main menu, and renamed to "One window" in split mode. + +** In split mode, the MIXAL window has its own statusbar to display + symbol values in it (instead of in the main window toolbar). + +** Bug fix: the visibility of split windows when changing mode is now + correctly handled. + +** Bug fix: the devices window is now correctly destroyed, avoiding + GTK warnings on gmixvm exit. + +--------------------------------------------------------------------------- +* Version 0.4 (22/07/01) + +** Split mode: gmixvm can now be run with the MIXVM, MIXAL and Devices + windows detached (instead of arranged in a notebook). + +** When running in split mode, the MIXVM, MIXAL and Devices windows + can be hidden. + +** Conditional breakpoints can be set in mixvm and gmixvm using the + commands 'sbp[rmco]', which cause the execution to stop when a + given register, memory cell contents, comparison flag or overflow + toggle change (e.g. 'sbpr A' will set a breakpoint on register A + contents change). Conditional breakpoints can be deleted using the + new commands 'cbp[rmco]'. + +** New vm command 'pbt' which prints a backtrace of the last executed + instructions. + +** The gmixvm main window displays the path to the current MIX file in + its title bar. + +** The mixvm and gmixvm configuration files are now stored in ~/.mdk + (instead of ~/.gmixvm). + +** The default device files directory is also ~/.mdk. It can be + configured using the new command 'devdir' or (in gmixvm) with the + new Settings->Devices dir menu command. + +** The commands 'tron' and 'troff' have been substituted by 'tracing + on|off'. + +** The trace flag is saved as a configuration parameter in mixvm and + gmixvm. + +** New vm commands: 'pedit'/'sedit' (print/set editor command) and + 'pasm'/'sasm' (print/set compile command). Their value is stored as + a config param also in mixvm. + +** New command 'timing' for setting on/off and printing the timing + statistics (both in gmixvm and mixvm). Its value is also stored as + a config param. + +** mixvm and gmixvm now save a history file so that they remember + commands typed in previous sessions. + +** Bug fix: changes in the device format are now correctly stored (gmixvm). + +--------------------------------------------------------------------------- +* Version 0.3.5 (23/06/01) + +** In gmixvm, when the mouse pointer is over a MIXAL source line, the + status bar shows the value of the variables appearing in this line. + +** The current symbol table can be displayed, in gmixvm, using the menu + command Debug->Symbols... + +** Bug fix: the load, compile and run file dialogs now get the correct + filename under linux. + +** Bug fix: fonts used by gmixvm are now always correctly saved. + +** Bug fix: 'psym' now works correctly in gmixvm. + +** Bug fix: the symbol table for a MIX file is now correctly recovered + both in gmixvm and mixvm (negative values where incorrectly + converted to a positive value). + +--------------------------------------------------------------------------- +* Version 0.3.4 (12/06/01) + +** Bug fix for a segfault which made gmixvm unusable in version 0.3.3. + +--------------------------------------------------------------------------- +* Version 0.3.3 (10/06/01) + +** The output of the contents of binary devices in gmixvm can be + configured to be in decimal or word format (for each block device). + +** The main gmixvm window is not shown until it is completely drawn. + +** The commands 'edit' and 'compile' are now understood by gmixvm. The + external programs used can be configured using the menu entry + Settings->External programs. + +** The commands 'edit' and 'compile' can be now executed without + argument (both in mixvm and gmixvm). When no argument is given, the + MIXAL source file corresponding to the currently loaded MIX program + is edited/compiled. + +** Bug in CON fixed : 'CON wexpr' didn't compile correctly unless wexpr + represented a valid instruction; now, wexpr can evaluate to an + arbitrary value (Vasilij Ozmetelenko). + +** The completion key for the gmixvm command prompt is now TAB + (instead of RETURN). + +** The gmixvm command prompt maintains now a history of previously + typed commands, which can be visited using the arrow keys (UP for + previous command, DOWN for next one). + +** When a file is reloaded by the virtual machine (both in mixvm and + gmixvm), the currently set breakpoints are conserved. + +** When compiling a source file which is not in the current directory, the + correct path is now stored in the compiled file. + +** Fixed a bug which caused gmixvm to segfault when creating the + virtual machine (Andrew Hood) + +** The GNU MDK documentation is now distributed under the GFDL + license. + +--------------------------------------------------------------------------- +* Version 0.3.2 (10/05/01) + +** The colors used for highlighting MIXAL source lines in gmixvm are now + customizable. + +** The fonts used in the different gmixvm widgets are now + customizable. + +** Input/output for all MIX block devices is shown in gmixvm. + +** All gmixvm customizations are stored in a configuration file + (inside ~/.gmixvm directory). + +** Device files used by gmixvm are stored in ~/.gmixvm, instead of the + working directory. + +** Output to binary devices works now correctly. + +** Bug on pmem fixed (thanks to Christoph von Nathusius and Jason + Uhlenkott). + +--------------------------------------------------------------------------- +* Version 0.3.1 (9/04/01) + +** New binary and html RPMs (RedHat) contributed by Agustin Navarro + . + +** The package can be correctly build in FreeBSD 4.2 (Ying-Chieh Liao) + +** Fixed configuration process when included gettext is used. + +** The info files are now properly categorized in a dir entry, so that + they can be properly installed. + +** Compilation warnings fixed. + +** getopt implementation provided for systems missing it. + +--------------------------------------------------------------------------- +* Version 0.3 (28/03/01) + +** MDK is now an official GNU package. + +** New GTK+ interface for the virtual machine (gmixvm). + +** New mixvm-Emacs/GUD interface via mixvm.el (Philip King). + +** Readline and history support for mixvm are now optional features. + +** JRED is now properly implemented (bug pointed out by + Vasilij Ozmetelenko). + +--------------------------------------------------------------------------- +* 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 on/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, 2001, 2002, 2003 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. + + +--- +$Id: NEWS,v 1.55 2005/09/20 20:18:58 jao Exp $ diff --git a/README b/README new file mode 100644 index 0000000..b693dba --- /dev/null +++ b/README @@ -0,0 +1,43 @@ +Welcome to GNU MDK. + +GNU MDK is part of the GNU project [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). + +Project homepage: http://www.gnu.org/software/mdk/mdk.html + +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. + +-- +$Id: README,v 1.3 2002/04/08 00:29:59 jao Exp $ \ No newline at end of file diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..5338c6d --- /dev/null +++ b/THANKS @@ -0,0 +1,59 @@ +Acknowledgements +**************** + + 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 () suggested various improvements to + the documentation and has always kept an eye on every MDK release. + + * Philip Ellis King () provided MIXAL test programs + pinpointing bugs in the first MDK release, and useful discussions + as well. Philip has also contributed with the Emacs port of + `mixvm' and influenced the `gmixvm' GUI design with insightful + comments and prototypes. + + * Pieter E.J. Pareit () is the author of + the Emacs MIXAL mode, and has also contributed many bug fixes. + + * Michael Scholz () is the author of the + German translation of MDK's user interface. + + * Sergey Poznyakoff() provided patches to + mixlib/mix_scanner.l improving MIXAL compliance. + + * Francesc Xavier Noria () kindly and thoroughly + reviewed the MDK documentation, providing insightful advice. + + * Agustin Navarro (), Ying-Chieh Liao + (), Adrian Bunk (), + Baruch Even () and Ronald Cole + () created and/or maintain packages of MDK + for different operating systems. + + * Jason Uhlenkott, Andrew Hood (), Radu Butnaru + (), Aleix Conchillo (), + Ruslan Batdalov (), WeiZheng + () and Sascha Wilde reported (sometimes with + fixes) several bugs in MDK. + + * Nelson H. F. Beebe (, + http://www.math.utah.edu/~beebe) has tested MDK in a lot of Unix + platforms, suggesting portability enhancements to the source + code. + + * Christoph von Nathusius (), Stephen Ramsay + () and Johan Swanljung () + tested MDK on different platforms. + + * Eli Bendersky (), Milan Bella + () and Jens Seidel reported several + documentation bugs. + + * MDK was inspired by Darius Bacon's MIXAL program + (http://www.accesscom.com/~darius/). + +-- +$Id: THANKS,v 1.20 2005/09/20 19:14:16 jao Exp $ + diff --git a/TODO b/TODO new file mode 100644 index 0000000..84b7dcc --- /dev/null +++ b/TODO @@ -0,0 +1,19 @@ +-*- mode: outline -*- + +* Version 1.2.2 +** gmixvm: list of last loaded programs +** gmixvm: history in terminal input dialog +** Add entries to concept index +** Sync docs with published book + +* Misc +** MIX types manipulation library in Scheme +** Macro recorder (implemented in Scheme) +** Add scheme functions to remove installed hooks + +** Allow MIXAL instructions as commands at the mixvm prompt + (e.g. MIX > exec LDA 2000) + +** gtkhtml for help system + +* $Id: TODO,v 1.12 2005/09/20 20:18:58 jao Exp $ diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..d76540d --- /dev/null +++ b/autogen.sh @@ -0,0 +1,79 @@ +#!/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 "(0.13.1 or a newer version if it is available)" + DIE=1 + } +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have autoconf installed to compile $PROJECT." + echo "(2.53 or a newer version if it is available)" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have automake installed to compile $PROJECT." + echo "(1.5 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." + 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 +} + +case $CC in +*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;; +esac + +echo "Running gettext's autopoint..." +autopoint --force + +echo "Running intltoolize" +intltoolize --copy --force --automake + +ACLOCAL_FLAGS="-I m4" +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 diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..4e38888 --- /dev/null +++ b/configure.in @@ -0,0 +1,175 @@ +# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# +# $Id: configure.in,v 1.38 2005/09/20 20:18:58 jao Exp $ +# +# 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([GNU MDK],1.2.1,[bug-mdk@gnu.org],mdk) +AM_INIT_AUTOMAKE(mdk,1.2.1) +AM_CONFIG_HEADER(config.h) + +AM_MAINTAINER_MODE + +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC +AC_HEADER_STDC + +AM_PROG_LEX +AC_PROG_RANLIB + +dnl additional c flags +CFLAGS="$CFLAGS -fno-strict-aliasing" +AC_SUBST(CFLAGS) + +dnl i18n stuff +AM_GNU_GETTEXT_VERSION(0.14) +AM_GNU_GETTEXT +AC_PROG_INTLTOOL([0.30], [no-xml]) + +test "x$prefix" = xNONE && prefix=$ac_default_prefix + +AH_TEMPLATE(LOCALEDIR,[locale directory]) +AC_DEFINE_UNQUOTED(LOCALEDIR, "${prefix}/share/locale") + +dnl Check for readline and history +AC_ARG_WITH(readline, +[ --without-readline build mixvm without 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]) +dnl old versions of readline use completion_matches instead +dnl of rl_completion_matches +AC_CHECK_FUNCS(rl_completion_matches,,) +fi + +dnl Check for guile +AC_ARG_WITH(guile, +[ --without-guile build MDK without Guile support], +[case "${withval}" in + yes) wguile=true ;; + no) wguile=false ;; + *) AC_MSG_ERROR(bad value ${withval} for --with-guile) ;; +esac], [wguile=true]) + +if test x$wguile = xtrue; then +dnl AC_CHECK_HEADER(guile/gh.h,,wguile=false) + AC_MSG_CHECKING(for Guile) + guile-config link > /dev/null || { + AC_MSG_RESULT(no) + wguile=false + } +fi + +if test x$wguile = xtrue; then + GUILE_CFLAGS="`guile-config compile`" + GUILE_LDFLAGS="`guile-config link`" + LIBS="$LIBS $GUILE_LDFLAGS" + CFLAGS="$CFLAGS $GUILE_CFLAGS" + AC_SUBST(MAKE_GUILE) + AC_MSG_RESULT(yes) +fi + +AM_CONDITIONAL(MAKE_GUILE, test x$wguile = xtrue) + +dnl Check for glib +PKG_CHECK_MODULES(GLIB,glib-2.0 >= 2.0) + +LIBS="$LIBS $GLIB_LIBS" +CFLAGS="$CFLAGS $GLIB_CFLAGS -DG_DISABLE_DEPRECATED" + +dnl Check if the gtk gui is required +AC_ARG_ENABLE(gui, +[ --disable-gui do not 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 +PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.4.0 libglade-2.0 >= 2.0.0 pango >= 1.4, + [LIBS="$LIBS $GTK_LIBS" CFLAGS="$CFLAGS $GTK_CFLAGS"], + [AC_MSG_WARN(Cannot find GTK+: the GUI shall not be built) + gui=false]) +fi + +if test x$gui = xtrue; then +CFLAGS="$CFLAGS -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED" +fi + +dnl use the provided getopt if gnu getopt is not available +AC_REPLACE_FUNCS(getopt_long) + +AM_CONDITIONAL(MAKE_GUI, test x$gui = xtrue) + +dnl AC_CANONICAL_HOST +case "${host_os}" in +darwin*) CFLAGS="$CFLAGS -Wall -traditional-cpp";; +*) CFLAGS="$CFLAGS -Wall";; +esac + +AC_SUBST(CFLAGS) + +AC_CONFIG_FILES( +Makefile +doc/Makefile +doc/img/Makefile +mixlib/Makefile +mixlib/testsuite/Makefile +mixguile/Makefile +mixutils/Makefile +mixgtk/Makefile +lib/Makefile +misc/Makefile +samples/Makefile +po/Makefile.in +intl/Makefile +) + +AC_OUTPUT + +if test x$readl = xtrue; then + rlinfo=", with readline support" +fi + +if test x$wguile = xtrue; then + guileinfo=", with guile support" +fi + +echo +echo "*** $PACKAGE_NAME $VERSION has been successfully configured. ***" +echo +echo "Type 'make' to build the following utilities:" +echo " - mixasm (MIX assembler)" +echo " - mixvm (MIX virtual machine${rlinfo}${guileinfo})" +if test x$gui = xtrue; then +echo " - gmixvm (mixvm GTK+ GUI${guileinfo})" +fi +if test x$wguile = xtrue; then +echo " - mixguile (the mixvm guile shell)" +fi +echo diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..b2b73f0 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,23 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2000, 2001, 2003, 2004 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. + +# $Id: Makefile.am,v 1.11 2004/08/06 12:14:07 jao Exp $ + +SUBDIRS = img +SUFFIXES = .html + +info_TEXINFOS = mdk.texi +mdk_TEXINFOS = mdk_intro.texi mdk_ack.texi mdk_tut.texi mdk_gstart.texi \ + mdk_mixvm.texi mdk_emacs.texi mdk_mixasm.texi mdk_bugs.texi \ + mdk_index.texi mdk_gmixvm.texi mdk_install.texi \ + mdk_mixguile.texi mdk_copying.texi mdk_findex.texi + diff --git a/doc/gendocs.sh b/doc/gendocs.sh new file mode 100755 index 0000000..7b8a3ca --- /dev/null +++ b/doc/gendocs.sh @@ -0,0 +1,285 @@ +#!/bin/sh +# gendocs.sh -- generate a GNU manual in many formats. This script is +# mentioned in maintain.texi. See the help message below for usage details. +# $Id: gendocs.sh,v 1.4 2005/09/20 20:18:58 jao Exp $ +# +# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you can either send email to this +# program's maintainer or write to: The Free Software Foundation, +# Inc.; 51 Franklin Street, Fifth Floor; Boston, MA 02110-1301, USA. +# +# Original author: Mohit Agarwal. +# Send bug reports and any other correspondence to bug-texinfo@gnu.org. + +prog="`basename \"$0\"`" +srcdir=`pwd` + +scripturl="http://savannah.gnu.org/cgi-bin/viewcvs/texinfo/texinfo/util/gendocs.sh" +templateurl="http://savannah.gnu.org/cgi-bin/viewcvs/texinfo/texinfo/util/gendocs_template" + +: ${MAKEINFO="makeinfo"} +: ${TEXI2DVI="texi2dvi -t @finalout"} +: ${DVIPS="dvips"} +: ${DOCBOOK2TXT="docbook2txt"} +: ${DOCBOOK2HTML="docbook2html"} +: ${DOCBOOK2PDF="docbook2pdf"} +: ${DOCBOOK2PS="docbook2ps"} +: ${GENDOCS_TEMPLATE_DIR="."} +unset CDPATH + +rcs_revision='$Revision: 1.4 $' +rcs_version=`set - $rcs_revision; echo $2` +program=`echo $0 | sed -e 's!.*/!!'` +version="gendocs.sh $rcs_version + +Copyright (C) 2005 Free Software Foundation, Inc. +There is NO warranty. You may redistribute this software +under the terms of the GNU General Public License. +For more information about these matters, see the files named COPYING." + +usage="Usage: $prog [OPTION]... PACKAGE MANUAL-TITLE + +Generate various output formats from PACKAGE.texinfo (or .texi or .txi) source. +See the GNU Maintainers document for a more extensive discussion: + http://www.gnu.org/prep/maintain_toc.html + +Options: + -o OUTDIR write files into OUTDIR, instead of manual/. + --docbook convert to DocBook too (xml, txt, html, pdf and ps). + --html ARG pass indicated ARG to makeinfo for HTML targets. + --help display this help and exit successfully. + --version display version information and exit successfully. + +Simple example: $prog emacs \"GNU Emacs Manual\" + +Typical sequence: + cd YOURPACKAGESOURCE/doc + wget \"$scripturl\" + wget \"$templateurl\" + $prog YOURMANUAL \"GNU YOURMANUAL - One-line description\" + +Output will be in a new subdirectory \"manual\" (by default, use -o OUTDIR +to override). Move all the new files into your web CVS tree, as +explained in the Web Pages node of maintain.texi. + +MANUAL-TITLE is included as part of the HTML of the overall +manual/index.html file. It should include the name of the package being +documented. manual/index.html is created by substitution from the file +$GENDOCS_TEMPLATE_DIR/gendocs_template. (Feel free to modify the +generic template for your own purposes.) + +If you have several manuals, you'll need to run this script several +times with different YOURMANUAL values, specifying a different output +directory with -o each time. Then write (by hand) an overall index.html +with links to them all. + +You can set the environment variables MAKEINFO, TEXI2DVI, and DVIPS to +control the programs that get executed, and GENDOCS_TEMPLATE_DIR to +control where the gendocs_template file is looked for. + +Email bug reports or enhancement requests to bug-texinfo@gnu.org. +" + +calcsize() +{ + size="`ls -ksl $1 | awk '{print $1}'`" + echo $size +} + +outdir=manual +html= +PACKAGE= +MANUAL_TITLE= + +while test $# -gt 0; do + case $1 in + --help) echo "$usage"; exit 0;; + --version) echo "$version"; exit 0;; + -o) shift; outdir=$1;; + --docbook) docbook=yes;; + --html) shift; html=$1;; + -*) + echo "$0: Unknown or ambiguous option \`$1'." >&2 + echo "$0: Try \`--help' for more information." >&2 + exit 1;; + *) + if test -z "$PACKAGE"; then + PACKAGE=$1 + elif test -z "$MANUAL_TITLE"; then + MANUAL_TITLE=$1 + else + echo "$0: extra non-option argument \`$1'." >&2 + exit 1 + fi;; + esac + shift +done + +if test -s $srcdir/$PACKAGE.texinfo; then + srcfile=$srcdir/$PACKAGE.texinfo +elif test -s $srcdir/$PACKAGE.texi; then + srcfile=$srcdir/$PACKAGE.texi +elif test -s $srcdir/$PACKAGE.txi; then + srcfile=$srcdir/$PACKAGE.txi +else + echo "$0: cannot find .texinfo or .texi or .txi for $PACKAGE in $srcdir." >&2 + exit 1 +fi + +if test ! -r $GENDOCS_TEMPLATE_DIR/gendocs_template; then + echo "$0: cannot read $GENDOCS_TEMPLATE_DIR/gendocs_template." >&2 + echo "$0: it is available from $templateurl." >&2 + exit 1 +fi + +echo Generating output formats for $srcfile + +cmd="${MAKEINFO} -o $PACKAGE.info $srcfile" +echo "Generating info files... ($cmd)" +eval $cmd +mkdir -p $outdir/ +tar czf $outdir/$PACKAGE.info.tar.gz $PACKAGE.info* +info_tgz_size="`calcsize $outdir/$PACKAGE.info.tar.gz`" +# do not mv the info files, there's no point in having them available +# separately on the web. + +cmd="${TEXI2DVI} $srcfile" +echo "Generating dvi ... ($cmd)" +eval $cmd + +# now, before we compress dvi: +echo Generating postscript... +${DVIPS} $PACKAGE -o +gzip -f -9 $PACKAGE.ps +ps_gz_size="`calcsize $PACKAGE.ps.gz`" +mv $PACKAGE.ps.gz $outdir/ + +# compress/finish dvi: +gzip -f -9 $PACKAGE.dvi +dvi_gz_size="`calcsize $PACKAGE.dvi.gz`" +mv $PACKAGE.dvi.gz $outdir/ + +cmd="${TEXI2DVI} --pdf $srcfile" +echo "Generating pdf ... ($cmd)" +eval $cmd +pdf_size="`calcsize $PACKAGE.pdf`" +mv $PACKAGE.pdf $outdir/ + +cmd="${MAKEINFO} -o $PACKAGE.txt --no-split --no-headers $srcfile" +echo "Generating ASCII... ($cmd)" +eval $cmd +ascii_size="`calcsize $PACKAGE.txt`" +gzip -f -9 -c $PACKAGE.txt >$outdir/$PACKAGE.txt.gz +ascii_gz_size="`calcsize $outdir/$PACKAGE.txt.gz`" +mv $PACKAGE.txt $outdir/ + +cmd="${MAKEINFO} --no-split --html -o $PACKAGE.html $html $srcfile" +echo "Generating monolithic html... ($cmd)" +rm -rf $PACKAGE.html # in case a directory is left over +eval $cmd +html_mono_size="`calcsize $PACKAGE.html`" +gzip -f -9 -c $PACKAGE.html >$outdir/$PACKAGE.html.gz +html_mono_gz_size="`calcsize $outdir/$PACKAGE.html.gz`" +mv $PACKAGE.html $outdir/ + +cmd="${MAKEINFO} --html -o $PACKAGE.html $html $srcfile" +echo "Generating html by node... ($cmd)" +eval $cmd +split_html_dir=$PACKAGE.html +( + cd ${split_html_dir} || exit 1 + tar -czf ../$outdir/${PACKAGE}.html_node.tar.gz -- *.html +) +html_node_tgz_size="`calcsize $outdir/${PACKAGE}.html_node.tar.gz`" +rm -f $outdir/html_node/*.html +mkdir -p $outdir/html_node/ +mv ${split_html_dir}/*.html $outdir/html_node/ +rmdir ${split_html_dir} + +echo Making .tar.gz for sources... +srcfiles=`ls *.texinfo *.texi *.txi *.eps 2>/dev/null` +tar cvzfh $outdir/$PACKAGE.texi.tar.gz $srcfiles +texi_tgz_size="`calcsize $outdir/$PACKAGE.texi.tar.gz`" + +if test -n "$docbook"; then + cmd="${MAKEINFO} -o - --docbook $srcfile > ${srcdir}/$PACKAGE-db.xml" + echo "Generating docbook XML... $(cmd)" + eval $cmd + docbook_xml_size="`calcsize $PACKAGE-db.xml`" + gzip -f -9 -c $PACKAGE-db.xml >$outdir/$PACKAGE-db.xml.gz + docbook_xml_gz_size="`calcsize $outdir/$PACKAGE-db.xml.gz`" + mv $PACKAGE-db.xml $outdir/ + + cmd="${DOCBOOK2HTML} -o $split_html_db_dir ${outdir}/$PACKAGE-db.xml" + echo "Generating docbook HTML... ($cmd)" + eval $cmd + split_html_db_dir=html_node_db + ( + cd ${split_html_db_dir} || exit 1 + tar -czf ../$outdir/${PACKAGE}.html_node_db.tar.gz -- *.html + ) + html_node_db_tgz_size="`calcsize $outdir/${PACKAGE}.html_node_db.tar.gz`" + rm -f $outdir/html_node_db/*.html + mkdir -p $outdir/html_node_db + mv ${split_html_db_dir}/*.html $outdir/html_node_db/ + rmdir ${split_html_db_dir} + + cmd="${DOCBOOK2TXT} ${outdir}/$PACKAGE-db.xml" + echo "Generating docbook ASCII... ($cmd)" + eval $cmd + docbook_ascii_size="`calcsize $PACKAGE-db.txt`" + mv $PACKAGE-db.txt $outdir/ + + cmd="${DOCBOOK2PS} ${outdir}/$PACKAGE-db.xml" + echo "Generating docbook PS... $(cmd)" + eval $cmd + gzip -f -9 -c $PACKAGE-db.ps >$outdir/$PACKAGE-db.ps.gz + docbook_ps_gz_size="`calcsize $outdir/$PACKAGE-db.ps.gz`" + mv $PACKAGE-db.ps $outdir/ + + cmd="${DOCBOOK2PDF} ${outdir}/$PACKAGE-db.xml" + echo "Generating docbook PDF... ($cmd)" + eval $cmd + docbook_pdf_size="`calcsize $PACKAGE-db.pdf`" + mv $PACKAGE-db.pdf $outdir/ +fi + +echo Writing index file... +curdate="`date '+%B %d, %Y'`" +sed \ + -e "s!%%TITLE%%!$MANUAL_TITLE!g" \ + -e "s!%%DATE%%!$curdate!g" \ + -e "s!%%PACKAGE%%!$PACKAGE!g" \ + -e "s!%%HTML_MONO_SIZE%%!$html_mono_size!g" \ + -e "s!%%HTML_MONO_GZ_SIZE%%!$html_mono_gz_size!g" \ + -e "s!%%HTML_NODE_TGZ_SIZE%%!$html_node_tgz_size!g" \ + -e "s!%%INFO_TGZ_SIZE%%!$info_tgz_size!g" \ + -e "s!%%DVI_GZ_SIZE%%!$dvi_gz_size!g" \ + -e "s!%%PDF_SIZE%%!$pdf_size!g" \ + -e "s!%%PS_GZ_SIZE%%!$ps_gz_size!g" \ + -e "s!%%ASCII_SIZE%%!$ascii_size!g" \ + -e "s!%%ASCII_GZ_SIZE%%!$ascii_gz_size!g" \ + -e "s!%%TEXI_TGZ_SIZE%%!$texi_tgz_size!g" \ + -e "s!%%DOCBOOK_HTML_NODE_TGZ_SIZE%%!$html_node_db_tgz_size!g" \ + -e "s!%%DOCBOOK_ASCII_SIZE%%!$docbook_ascii_size!g" \ + -e "s!%%DOCBOOK_PS_GZ_SIZE%%!$docbook_ps_gz_size!g" \ + -e "s!%%DOCBOOK_PDF_SIZE%%!$docbook_pdf_size!g" \ + -e "s!%%DOCBOOK_XML_SIZE%%!$docbook_xml_size!g" \ + -e "s!%%DOCBOOK_XML_GZ_SIZE%%!$docbook_xml_gz_size!g" \ + -e "s,%%SCRIPTURL%%,$scripturl,g" \ + -e "s!%%SCRIPTNAME%%!$prog!g" \ +$GENDOCS_TEMPLATE_DIR/gendocs_template >$outdir/index.html + +echo "Done! See $outdir/ subdirectory for new files." diff --git a/doc/gendocs_template b/doc/gendocs_template new file mode 100644 index 0000000..3fd6fd2 --- /dev/null +++ b/doc/gendocs_template @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- $Id: gendocs_template,v 1.4 2005/09/20 20:18:58 jao Exp $ --> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> + +<head> +<title>%%TITLE%% - GNU Project - Free Software Foundation (FSF) + + + + + + + + + + + + + +

%%TITLE%%

+ +
Free Software Foundation
+
last updated %%DATE%%
+

+ +  [image of the head of a GNU] + +(no gifs due to patent problems) +

+
+ +

This manual (%%PACKAGE%%) is available in the following formats:

+ + + +

(This page generated by the %%SCRIPTNAME%% +script.)

+ + + + + diff --git a/doc/img/Makefile.am b/doc/img/Makefile.am new file mode 100644 index 0000000..f59647e --- /dev/null +++ b/doc/img/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2001, 2004 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 = ss_mix.jpg ss_mixal.jpg ss_devices.jpg ss_worddlg.jpg \ + ss_mix.txt ss_devform.jpg ss_extprog.jpg ss_symbols.jpg \ + ss_devdir.jpg ss_split.jpg + diff --git a/doc/img/ss_devdir.jpg b/doc/img/ss_devdir.jpg new file mode 100644 index 0000000..009fa43 Binary files /dev/null and b/doc/img/ss_devdir.jpg differ diff --git a/doc/img/ss_devform.jpg b/doc/img/ss_devform.jpg new file mode 100644 index 0000000..a93e5a0 Binary files /dev/null and b/doc/img/ss_devform.jpg differ diff --git a/doc/img/ss_devices.jpg b/doc/img/ss_devices.jpg new file mode 100644 index 0000000..ecb3679 Binary files /dev/null and b/doc/img/ss_devices.jpg differ diff --git a/doc/img/ss_extprog.jpg b/doc/img/ss_extprog.jpg new file mode 100644 index 0000000..f5607de Binary files /dev/null and b/doc/img/ss_extprog.jpg differ diff --git a/doc/img/ss_mix.jpg b/doc/img/ss_mix.jpg new file mode 100644 index 0000000..8b4080f Binary files /dev/null and b/doc/img/ss_mix.jpg differ diff --git a/doc/img/ss_mix.txt b/doc/img/ss_mix.txt new file mode 100644 index 0000000..757026e --- /dev/null +++ b/doc/img/ss_mix.txt @@ -0,0 +1,31 @@ +|-----------------------------------------------------------| +| Menu | +|-----------------------------------------------------------| +| | +| | +| | +| | +| MIXVM / MIXAL / Devices | +| | +| | +| | +| | +| | +| | +|-----------------------------------------------------------| +| | +| Command output | +| | +| | +| | +|-----------------------------------------------------------| +| Command prompt | +|-----------------------------------------------------------| +| Status bar | +|-----------------------------------------------------------| + + + + + + diff --git a/doc/img/ss_mixal.jpg b/doc/img/ss_mixal.jpg new file mode 100644 index 0000000..5227b5a Binary files /dev/null and b/doc/img/ss_mixal.jpg differ diff --git a/doc/img/ss_split.jpg b/doc/img/ss_split.jpg new file mode 100644 index 0000000..66fd4a7 Binary files /dev/null and b/doc/img/ss_split.jpg differ diff --git a/doc/img/ss_symbols.jpg b/doc/img/ss_symbols.jpg new file mode 100644 index 0000000..6a0e827 Binary files /dev/null and b/doc/img/ss_symbols.jpg differ diff --git a/doc/img/ss_worddlg.jpg b/doc/img/ss_worddlg.jpg new file mode 100644 index 0000000..fc19000 Binary files /dev/null and b/doc/img/ss_worddlg.jpg differ diff --git a/doc/mdk.texi b/doc/mdk.texi new file mode 100644 index 0000000..ce86b37 --- /dev/null +++ b/doc/mdk.texi @@ -0,0 +1,248 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename mdk.info +@settitle GNU MIX Development Kit (mdk) +@syncodeindex pg cp +@finalout +@setchapternewpage odd +@c $Id: mdk.texi,v 1.28 2005/09/20 21:00:22 jao Exp $ +@c %**end of header + +@set UPDATED September, 2005 +@set EDITION 1.2.1 +@set VERSION 1.2.1 +@set JAO Jose Antonio Ortega Ruiz +@set PHILIP Philip E. King +@set PIETER Pieter E. J. Pareit +@set MIKE Michael Scholz + +@copying +This manual is for GNU MDK (version @value{VERSION}, @value{UPDATED}), +a set of utilities for developing programs using Donald Knuth's MIX +mythical computer and MIXAL, its assembly language. + +Copyright @copyright{} 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,'' +and with the Back-Cover Texts as in (a) below. A copy of the +license is included in the section entitled ``GNU Free Documentation +License.'' + +(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify +this GNU Manual, like GNU software. Copies published by the Free +Software Foundation raise funds for GNU development.'' +@end quotation +@end copying + +@dircategory GNU programming tools +@direntry +* MDK: (mdk). The GNU MIX Development Kit. +@end direntry + + +@footnotestyle separate + +@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} (@email{jao@@gnu.org}) +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@shortcontents +@contents + +@ifnottex +@node Top, Introduction, (dir), (dir) + +@insertcopying + +GNU MDK was written and designed by @value{JAO}. + +@value{PIETER} is the author of the Emacs @code{MIXAL} mode +(@pxref{MIXAL mode}), and has also contributed many bug fixes. + +@value{PHILIP} has contributed to this package development with many +helpful discussions, as well as actual code (@pxref{GUD integration}). + +@value{MIKE} is the author of the German translation of @sc{mdk}'s +user interface. + +@end ifnottex + +@menu +* Introduction:: +* Acknowledgments:: +* Installing MDK:: Installing GNU MDK from the source tarball. +* MIX and MIXAL tutorial:: Learn the innards of MIX and MIXAL. +* Getting started:: Basic usage of the @sc{mdk} tools. +* Emacs tools:: Programming the MIX using Emacs. +* mixasm:: Invoking the MIXAL assembler. +* mixvm:: Invoking and using the MIX virtual machine. +* gmixvm:: Invoking and using the GTK+ virtual machine. +* mixguile:: Invoking and using the Scheme virtual machine. +* Problems:: Reporting bugs. +* Copying:: @sc{mdk} licensing terms. +* Concept Index:: Index of concepts. +* Instructions and commands:: Index of MIXAL instructions and MIXVM commands. + + + +@detailmenu + --- The Detailed Node Listing --- + +Installing @sc{mdk} + +* Download:: +* Requirements:: +* Basic installation:: +* Emacs support:: +* Special configure flags:: +* Supported platforms:: + +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 programs. +* Using mixguile:: Using the Scheme interpreter to run and + debug your programs. +* Using Scheme in mixvm and gmixvm:: + +Running the program + +* Non-interactive mode:: Running your programs non-interactively. +* Interactive mode:: Running programs interactively. +* Debugging:: Commands for debugging your programs. + +Using @code{mixguile} + +* The mixguile shell:: Using the Scheme MIX virtual machine. +* Additional functions:: Scheme functions accessing the VM. +* Defining new functions:: Defining your own Scheme functions. +* Hook functions:: Using command and break hook functions. +* Scheme scripts:: + +Hook functions + +* Command hooks:: +* Break hooks:: + +Emacs tools + +* MIXAL mode:: Editing MIXAL files. +* GUD integration:: Invoking @code{mixvm} within Emacs. + +MIXAL mode + +* Basics:: Editing code, font locking and indentation. +* Help system:: Using the interactive help system. +* Compiling and running:: Invoking compiler and/or virtual machine. + +@code{mixasm}, the MIXAL assembler + +* Invoking mixasm:: + +@code{mixvm}, the MIX computer simulator + +* Invocation:: +* 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. +* Configuration commands:: Changing and storing mixvm settings. +* Scheme commands:: + +@code{gmixvm}, the GTK virtual machine + +* Invoking gmixvm:: +* MIXVM console:: Using @code{mixvm} commands. +* MIX virtual machine:: The MIX virtual machine window. +* MIXAL source view:: Viewing the MIXAL source code. +* MIX devices view:: Device output. +* Menu and status bars:: Available menu commands. + +@code{mixguile}, the Scheme virtual machine + +* Invoking mixguile:: Command line options. +* Scheme functions reference:: Scheme functions accessing the VM. + +Scheme functions reference + +* mixvm wrappers:: Functions invoking mixvm commands. +* Hooks:: Adding hooks to mixvm commands. +* Additional VM functions:: Functions accessing the MIX virtual machine. + +Copying + +* GNU General Public License:: +* GNU Free Documentation License:: + +@end detailmenu +@end menu + +@include mdk_intro.texi +@include mdk_ack.texi +@include mdk_install.texi +@include mdk_tut.texi +@include mdk_gstart.texi +@include mdk_emacs.texi +@include mdk_mixasm.texi +@include mdk_mixvm.texi +@include mdk_gmixvm.texi +@include mdk_mixguile.texi +@include mdk_bugs.texi +@include mdk_copying.texi +@include mdk_index.texi +@include mdk_findex.texi + +@bye + diff --git a/doc/mdk_ack.texi b/doc/mdk_ack.texi new file mode 100644 index 0000000..807e276 --- /dev/null +++ b/doc/mdk_ack.texi @@ -0,0 +1,63 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_ack.texi,v 1.15 2005/09/20 00:26:00 jao Exp $ + +@node Acknowledgments, Installing MDK, Introduction, Top +@comment node-name, next, previous, up +@unnumbered Acknowledgements + +Many people have further contributed to @sc{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. + +@itemize @bullet +@item Richard Stallman +suggested various improvements to the documentation and has always +kept an eye on each @sc{mdk} release. + +@item Philip Ellis King +provided MIXAL test programs pinpointing bugs in the first @sc{mdk} +release, and useful discussions as well. Philip has also contributed +with the Emacs port of @code{mixvm} and influenced the @code{gmixvm} GUI +design with insightful comments and prototypes. + +@item Pieter E J Pareit +is the author of the Emacs MIXAL mode, and has also contributed many +bug fixes. + +@item Michael Scholz +is the author of the German translation of @sc{mdk}'s user interface. + +@item Sergey Poznyakoff +provided patches to mixlib/mix_scanner.l improving MIXAL compliance. + +@item Francesc Xavier Noria +kindly and thoroughly reviewed the @sc{mdk} documentation, providing +insightful advice. + +@item Nelson H. F. Beebe +has tested @sc{mdk} in a lot of Unix platforms, suggesting portability +enhancements to the source code. + +@item Agustin Navarro, Ying-Chieh Liao, Adrian Bunk, Baruch Even, and Ronald Cole +ported @sc{mdk} to different platforms, and created and/or maintain +packages for it. + +@item Jason Uhlenkott, Andrew Hood, Aleix Conchillo, Radu Butnaru, Ruslan Batdalov, WeiZheng and Sascha Wilde +reported bugs and suggested fixes to them. + +@item Eli Bendersky, Milan Bella and Jens Seidel reported bugs on the documentation. + +@item Christoph von Nathusius, Stephen Ramsay and Johan Swanljung +tested @sc{mdk} on different platforms, and helped fix the configuration +process in them. + +@item @sc{mdk} was inspired by Darius Bacon's +@uref{http://www.accesscom.com/@/~darius/, MIXAL program}. + +@end itemize + diff --git a/doc/mdk_bugs.texi b/doc/mdk_bugs.texi new file mode 100644 index 0000000..1b18064 --- /dev/null +++ b/doc/mdk_bugs.texi @@ -0,0 +1,24 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_bugs.texi,v 1.6 2004/08/03 13:23:06 jao Exp $ + +@node Problems, Copying, mixguile, 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_copying.texi b/doc/mdk_copying.texi new file mode 100644 index 0000000..8aa5e90 --- /dev/null +++ b/doc/mdk_copying.texi @@ -0,0 +1,866 @@ +@node Copying, Concept Index, Problems, Top +@appendix Copying + +@menu +* GNU General Public License:: +* GNU Free Documentation License:: +@end menu + +GNU MDK is distributed under the GNU General Public License (GPL) and +this manual under the GNU Free Documentation License (GFDL). + +@node GNU General Public License, GNU Free Documentation License, Copying, Copying +@appendixsec GNU General Public License +@cindex GPL, GNU General Public License + +@lowersections + +@center Version 2, June 1991 + +@display +Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 + + + +@node GNU Free Documentation License +@appendixsec GNU Free Documentation License + +@cindex FDL, GNU Free Documentation License +@center Version 1.2, November 2002 + +@display +Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display + +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document @dfn{free} in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The ``Document'', below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as ``you''. You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section +of the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not ``Transparent'' is called ``Opaque''. + +Examples of suitable formats for Transparent copies include plain +@sc{ascii} without markup, Texinfo input format, La@TeX{} input +format, @acronym{SGML} or @acronym{XML} using a publicly available +@acronym{DTD}, and standard-conforming simple @acronym{HTML}, +PostScript or @acronym{PDF} designed for human modification. Examples +of transparent image formats include @acronym{PNG}, @acronym{XCF} and +@acronym{JPG}. Opaque formats include proprietary formats that can be +read and edited only by proprietary word processors, @acronym{SGML} or +@acronym{XML} for which the @acronym{DTD} and/or processing tools are +not generally available, and the machine-generated @acronym{HTML}, +PostScript or @acronym{PDF} produced by some word processors for +output purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +A section ``Entitled XYZ'' means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as ``Acknowledgements'', +``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' +of such a section when you modify the Document means that it remains a +section ``Entitled XYZ'' according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +@item +COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +@enumerate A +@item +Use in the Title Page (and on the covers, if any) a title distinct +from that of the Document, and from those of previous versions +(which should, if there were any, be listed in the History section +of the Document). You may use the same title as a previous version +if the original publisher of that version gives permission. + +@item +List on the Title Page, as authors, one or more persons or entities +responsible for authorship of the modifications in the Modified +Version, together with at least five of the principal authors of the +Document (all of its principal authors, if it has fewer than five), +unless they release you from this requirement. + +@item +State on the Title page the name of the publisher of the +Modified Version, as the publisher. + +@item +Preserve all the copyright notices of the Document. + +@item +Add an appropriate copyright notice for your modifications +adjacent to the other copyright notices. + +@item +Include, immediately after the copyright notices, a license notice +giving the public permission to use the Modified Version under the +terms of this License, in the form shown in the Addendum below. + +@item +Preserve in that license notice the full lists of Invariant Sections +and required Cover Texts given in the Document's license notice. + +@item +Include an unaltered copy of this License. + +@item +Preserve the section Entitled ``History'', Preserve its Title, and add +to it an item stating at least the title, year, new authors, and +publisher of the Modified Version as given on the Title Page. If +there is no section Entitled ``History'' in the Document, create one +stating the title, year, authors, and publisher of the Document as +given on its Title Page, then add an item describing the Modified +Version as stated in the previous sentence. + +@item +Preserve the network location, if any, given in the Document for +public access to a Transparent copy of the Document, and likewise +the network locations given in the Document for previous versions +it was based on. These may be placed in the ``History'' section. +You may omit a network location for a work that was published at +least four years before the Document itself, or if the original +publisher of the version it refers to gives permission. + +@item +For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve +the Title of the section, and preserve in the section all the +substance and tone of each of the contributor acknowledgements and/or +dedications given therein. + +@item +Preserve all the Invariant Sections of the Document, +unaltered in their text and in their titles. Section numbers +or the equivalent are not considered part of the section titles. + +@item +Delete any section Entitled ``Endorsements''. Such a section +may not be included in the Modified Version. + +@item +Do not retitle any existing section to be Entitled ``Endorsements'' or +to conflict in title with any Invariant Section. + +@item +Preserve any Warranty Disclaimers. +@end enumerate + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties---for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled ``History'' +in the various original documents, forming one section Entitled +``History''; likewise combine any sections Entitled ``Acknowledgements'', +and any sections Entitled ``Dedications''. You must delete all +sections Entitled ``Endorsements.'' + +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an ``aggregate'' if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled ``Acknowledgements'', +``Dedications'', or ``History'', the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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 +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +@uref{http://www.gnu.org/copyleft/}. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. +@end enumerate + +@page +@appendixsubsec ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group + Copyright (C) @var{year} @var{your name}. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. +@end group +@end smallexample + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the ``with...Texts.'' line with this: + +@smallexample +@group + with the Invariant Sections being @var{list their titles}, with + the Front-Cover Texts being @var{list}, and with the Back-Cover Texts + being @var{list}. +@end group +@end smallexample + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + +@c Local Variables: +@c ispell-local-pdict: "ispell-dict" +@c End: + diff --git a/doc/mdk_emacs.texi b/doc/mdk_emacs.texi new file mode 100644 index 0000000..e0c6973 --- /dev/null +++ b/doc/mdk_emacs.texi @@ -0,0 +1,136 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@node Emacs tools, mixasm, Getting started, Top +@chapter Emacs tools + +Everyone writing code knows how important a good editor is. Most +systems already come with Emacs, and excellent programmer's editor. +@sc{mdk} adds support to Emacs for both writing and debugging MIX +programs. A major mode for MIXAL source files eases edition of your +code, while integration with Emacs' debugging interface +(@acronym{GUD}) lets you use @code{mixvm} without leaving your +favourite text editor. + +This chapter shows how to use the Elisp modules included in @sc{mdk}, +assuming that you have followed the installation instructions in +@xref{Emacs support}. + +@menu +* MIXAL mode:: Editing MIXAL files. +* GUD integration:: Invoking @code{mixvm} within Emacs. +@end menu + +@node MIXAL mode, GUD integration, Emacs tools, Emacs tools +@section MIXAL mode + +The module @file{mixal-mode.el} provides a new mode, mixal-mode, for +editing MIXAL source files@footnote{mixal-mode has been developed and +documented by @value{PIETER}}. When everything is installed correctly, +Emacs will select it as the major mode for editing files with extension +@code{.mixal}. You can also activate mixal-mode in any buffer +issuing the Emacs command @code{M-x mixal-mode}. + +@menu +* Basics:: Editing code, font locking and indentation. +* Help system:: Using the interactive help system. +* Compiling and running:: Invoking compiler and/or virtual machine. +@end menu + +@node Basics, Help system, MIXAL mode, MIXAL mode +@comment node-name, next, previous, up +@subsection Basics + +The mode for editing mixal source files is inherited from +fundamental-mode, meaning that all your favorite editing operations +will still work. If you want a short introduction to Emacs, type +@kbd{C-h t} inside Emacs to start the tutorial. + +Mixal mode adds font locking. If you do not have font locking globally +enabled, you can turn it on for mixal-mode by placing the following +line in your @file{.emacs} file: + +@lisp +(add-hook 'mixal-mode-hook 'turn-on-font-lock) +@end lisp + +You can also customize the colors used to colour your mixal code by +changing the requisite faces. This is the list of faces used by +mixal-mode: + +@itemize +@item @var{font-lock-comment-face} +Face to use for comments. +@item @var{mixal-font-lock-label-face} +Face to use for label names. +@item @var{mixal-font-lock-operation-code-face} +Face to use for operation code names. +@item @var{mixal-font-lock-assembly-pseudoinstruction-face} +Face to use for assembly pseudo-instruction names. +@end itemize + +@node Help system, Compiling and running, Basics, MIXAL mode +@comment node-name, next, previous, up +@subsection Help system + +When coding your program, you will be thinking, looking up +documentation and editing files. Emacs already helps you with editing +files, but Emacs can do much more. In particular, looking up +documentation is one of its strong points. Besides the info system +(which you are probably already using), mixal-mode defines commands +for getting particular information about a MIX operation code. + +With @kbd{M-x mixal-describe-operation-code} (or its keyboard shortcut +@kbd{C-h o}) you will get the documentation about a particular MIX +operation code. Keep in mind that these are not assembly (MIXAL) +pseudoinstructions. When the @code{point} is around a MIXAL +pseudoinstruction in your source file, Emacs will recognize it and +will suggest the right MIX operation code. + +@node Compiling and running, , Help system, MIXAL mode +@comment node-name, next, previous, up +@subsection Compiling and running + +After you have written your MIXAL program, you'll probably want to +test it. This can be done with the MIX virtual machine. First you will +need to compile your code into MIX byte code. This can be done within +Emacs with the command @kbd{M-x compile} (@kbd{C-c c}). In case of +compilation errors, you can jump to the offending source code line +with @kbd{M-x next-error}. + +Once the program compiles without errors, you can debug or run +it. To invoke the debugger, use @kbd{M-x mixal-debug} (@kbd{C-c d}). +Emacs will open a @code{GUD} buffer where you can +use the debugging commands described in @xref{mixvm}. + +If you just want to execute the program, you can do so with @kbd{M-x +mixal-run} (@kbd{C-c r}). This will invoke mixvm, +execute the program and show its output in a separate buffer. + +@node GUD integration, , MIXAL mode, Emacs tools +@section GUD integration + +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_findex.texi b/doc/mdk_findex.texi new file mode 100644 index 0000000..24a269f --- /dev/null +++ b/doc/mdk_findex.texi @@ -0,0 +1,11 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_findex.texi,v 1.3 2004/08/03 13:23:06 jao Exp $ + +@node Instructions and commands, , Concept Index, Top +@unnumbered Instructions and commands +@printindex fn diff --git a/doc/mdk_gmixvm.texi b/doc/mdk_gmixvm.texi new file mode 100644 index 0000000..bddb362 --- /dev/null +++ b/doc/mdk_gmixvm.texi @@ -0,0 +1,394 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_gmixvm.texi,v 1.18 2004/08/03 13:23:06 jao Exp $ + +@node gmixvm, mixguile, mixvm, Top +@comment node-name, next, previous, up +@chapter @code{gmixvm}, the GTK virtual machine +@cindex @code{gmixvm} +@cindex GUI +@cindex GTK+ + +This chapter describes the graphical MIX virtual machine emulator +shipped with @sc{mdk}. In addition to having all the command-oriented +functionalities of the other virtual machines (@code{mixvm} and +@code{mixguile}), @code{gmixvm} offers you a graphical interface +displaying the status of the virtual machine, the source code of the the +downloaded programs and the contents of the MIX devices. + +@menu +* Invoking gmixvm:: +* MIXVM console:: Using @code{mixvm} commands. +* MIX virtual machine:: The MIX virtual machine window. +* MIXAL source view:: Viewing the MIXAL source code. +* MIX devices view:: Device output. +* Menu and status bars:: Available menu commands. +@end menu + +@node Invoking gmixvm, MIXVM console, 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 [-vhuq] [--version] [--help] [--usage] [--noinit] +@end example +@noindent +at your command prompt, where the options have the following meanings: + +@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 -q +@defoptx --noinit +Do not load the Guile initialisation file @code{~/.mdk/mixguile.scm} at +startup. This file contains any local Scheme code to be executed by the +embedded Guile interpreter at startup (@pxref{Using Scheme in mixvm and +gmixvm}). +@end defopt + +Typing @code{gmixvm} or @code{gmixvm -q} at your command prompt, the +main window will appear, offering you a graphical interface to run and +debug your MIX programs. + +@ifinfo +@image{img/ss_mix, 400pt} +@end ifinfo + +@ifhtml +@image{../img/ss_mix, 400pt} +@end ifhtml + +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 +These three windows can be detached from the notebook, using either +the penultimate toolbar button (which detachs the currently visible +notebook page) or the menu entries under @code{@w{View->Detached windows}}. + +@ifhtml +Here is an screenshot showing how @code{gmixvm} looks like when running +with a couple of detached windows: + +@image{../img/ss_split, 420pt} + +@end ifhtml + +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. These widgets implement a @code{mixvm} +console which offers almost the same functionality as its +@acronym{CLI} counterpart. + +When @code{gmixvm} is run, it creates a directory named @file{.mdk} in +your home directory (if it does not already exist). The @file{.mdk} +directory contains the program settings, the device files used by your +MIX programs (@pxref{Devices}), and a command history file. + +The following sections describe the above mentioned components of +@code{gmixvm}. + +@node MIXVM console, MIX virtual machine, Invoking gmixvm, gmixvm +@comment node-name, next, previous, up +@section MIXVM console + +In the lower half of the @code{gmixvm} main window, you will find a +command text entry and, above it, an echo area. These widgets offer you +the same functionality as its @acronym{CLI} counterpart, @code{mixvm} +(@pxref{mixvm}). You can issue almost all @code{mixmv} commands at the +@code{gmixvm}'s command prompt in order to manipulate the MIX virtual +machine. Please refer to @xref{mixvm}, for a description of these +commands, and to @xref{Getting started}, for a tutorial on using the MIX +virtual machine. The command prompt offers command line completion for +partially typed commands using the @key{TAB} key; e.g., if you type + +@example +lo @key{TAB} +@end example +@noindent +the command is automatically completed to @code{load}. If multiple +completions are available, they will be shown in the echo area. Thus, +typing + +@example +p @key{TAB} +@end example +@noindent +will produce the following output on the echo area: + +@example +Completions: +pc psym preg pflags pall +pmem +@end example +@noindent +which lists all the available commands starting with @code{p}. In +addition, the command prompt maintains a history of typed commands, +which can be recovered using the arrow up and down keys. As mentioned +above, a file containing previous sessions' commands is stored in the +configuration directory @file{~/.mdk}, and reloaded every time you start +@code{gmixvm}. + +You can change the font used to display the issued commands and the +messages in the echo area using the @code{@w{Settings->Change font->Command +prompt}} and @code{@w{Settings->Change font->Command log}} menu commands. + +@node MIX virtual machine, MIXAL source view, MIXVM console, 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). + +If you click any register entry, you will be prompted for a new register's +contents. + +@ifhtml +The next figure shows the enter word dialog. + +@image{../img/ss_worddlg, 250pt} + +@end ifhtml + +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. + +The register contents are shown as a list of MIX bytes plus sign. If you +place the mouse pointer over any of them, the decimal value of this MIX +word will appear inside a tooltip. + +You can change the font used to display the MIX virtual machine contents +using the @code{@w{Settings->Change font->MIX}} menu command. + +@node MIXAL source view, MIX devices view, MIX virtual machine, gmixvm +@comment node-name, next, previous, up +@section MIXAL source view + +The second notebook's page, dubbed Source, shows you the MIXAL source of +the currently loaded MIX file. + +@ifhtml +@image{../img/ss_mixal, 400pt} +@end ifhtml + +The information is presented in four columns. The first column +displays little icons showing the current program pointer and any set +breakpoints. The second and third columns show the address and memory +contents of the compiled MIX instruction, while the last one displays +its corresponding MIXAL representation, together with the source file +line number. You can set/unset breakpoints by clicking on any line +that has an associated memory address. + +You can change the font used to display the MIXAL source code +using the @code{@w{Settings->Change font->MIXAL}} menu command. + +@node MIX devices view, Menu and status bars, MIXAL source view, gmixvm +@comment node-name, next, previous, up +@section MIX devices view + +The last notebook page, dubbed Devices, shows you the output/input +to/from MIX block devices (the console, line printer, paper tape, +disks, card and tapes @pxref{Devices}) produced by the running +program. + +@ifhtml + +@image{../img/ss_devices, 400pt} + +@end ifhtml + +Input device contents is read from files located in the @file{~/.mdk} +directory, and the output is also written to files at the same +location. Note that device tabs will appear as they are used by the MIX +program being run, and that loading a new MIX program will close all +previously open devices. + +The input/output for binary block devices (tapes and disks) is a list +of MIX words, which can be displayed either in decimal or word format +(e.g. @w{- 67} or @w{- 00 00 00 01 03}). The format used by +@code{gmixvm} can be configured using the @code{@w{Settings->Device output}} +menu command for each binary device. + +You can change the font used to display the devices content +using the @code{@w{Settings->Change font->Devices}} menu command. + +@node Menu and status bars, , MIX devices view, 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 Edit... +Opens a file dialog that lets your specify a MIXAL source file to be +edited. It is equivalent to the @code{mixvm}'s @code{edit} command +(@pxref{File commands}). The program used for editing can be specified +using the menu entry @code{@w{Settings->External programs}}, or using the +@code{mixvm} command @code{sedit}. +@end deffn + +@deffn File Compile... +Opens a file dialog that lets your specify a MIXAL source file to be +compiled. It is equivalent to the @code{mixvm}'s @code{compile} command +(@pxref{File commands}). The command used for compiling can be specified +using the menu entry @code{@w{Settings->External programs}}, or using the +@code{mixvm} command @code{sasm}. +@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 @w{Clear breakpoints} +Clears all currently set breakpoints. It is equivalent to the +@code{mixvm}'s @code{cabp} command. +@end deffn + +@deffn Debug Symbols... +Opens a dialog showing the list of symbols defined in the currently +loaded MIX program. The font used to display this list can be +customised using the meny entry @code{@w{Settings->Change font->Symbol +list}}. + +@ifhtml + +@image{../img/ss_symbols, 250pt} + +@end ifhtml + +@end deffn + +@deffn View @w{Toolbar(s)} +Toggles the toolbar(s) in the @code{gmixvm} window(s) (when notebook +pages are detached, each one has its own toolbar). +@end deffn + +@deffn View @w{Detached windows} @w{Virtual machine} +@deffnx View @w{Detached windows} Source +@deffnx View @w{Detached windows} Devices + +These toggles let you detach (or re-attach) the corresponding notebook +page. + +@end deffn + +@deffn Settings @w{Change font} +Lets you change the font used in the various @code{gmixv} widgets +(i.e. commad prompt, command log, Virtual machine, Source, Devices and +Symbol list). There is also an entry (@code{All}) to change all fonts +at once. +@end deffn + +@deffn Settings @w{Device output...} +Opens a dialog that lets you specify which format shall be used to show +the contents of MIX binary block devices. + +@ifhtml +@image{../img/ss_devform, 250pt} +@end ifhtml + +The available formats are decimal (e.g. @w{-1234}) and MIX word +(e.g. @w{- 00 00 00 19 18}). +@end deffn + +@deffn Settings @w{Devices dir...} +Opens a dialog that lets you choose where the MIX device files will be +stored (@file{~/.mdk} is the default location). + +@ifhtml +@image{../img/ss_devdir, 250pt} +@end ifhtml + +You can also specify the devices directory using the @code{mixvm} +command @code{sddir} (@pxref{Configuration commands}). + +@end deffn + +@deffn Settings @w{External programs...} +This menu command opens a dialog that lets you specify the commands used +for editing and compiling MIXAL source files. + +@ifhtml +@image{../img/ss_extprog, 250pt} +@end ifhtml + +The commands are specified as template strings, where the control +substring @code{%s} will be substituted by the actual file name. Thus, +if you want to edit programs using @code{vi} running in an @code{xterm}, +you must enter the command template @code{@w{xterm -e vi %s}} in the +corresponding dialog entry. These settings can also be changed using the +@code{mixvm} commands @code{sedit} and @code{sasm} (@pxref{Configuration +commands}). +@end deffn + + +@deffn Settings Save +Saves the current settings. +@end deffn + +@deffn Settings @w{Save on exit} +Mark this checkbox if you want @code{gmixvm} to save its settings +every time you quit the program. +@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. In addition, when the mouse pointer is over a MIXAL source +file line that contains symbols, a list of these symbols with their +values will appear in the status bar. diff --git a/doc/mdk_gstart.texi b/doc/mdk_gstart.texi new file mode 100644 index 0000000..9eab3f6 --- /dev/null +++ b/doc/mdk_gstart.texi @@ -0,0 +1,1058 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_gstart.texi,v 1.17 2004/08/01 21:43:29 jao Exp $ + +@node Getting started, Emacs tools, MIX and MIXAL tutorial, Top +@chapter Getting started +@cindex tutorial + +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 programs. +* Using mixguile:: Using the Scheme interpreter to run and + debug your programs. +* Using Scheme in mixvm and gmixvm:: +@end menu + +@node Writing a source file, Compiling, Getting started, Getting started +@section Writing a source file +@cindex MIXAL +@cindex source file +@cindex .mixal 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 in 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 7 and 8 above), or an assembly +pseudoinstruction (e.g., the @code{ORIG} pseudoinstruction in line +6@footnote{If an @code{ORIG} directive is not used, the program will +be loaded by the virtual machine at address 0. @code{ORIG} allows +allocating the executable code where you see fit.}. +@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 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. Note that double-quotes (") are not part of the MIX character +set, and, therefore, no escape characters are needed within +@code{ALF}'s operands.}. + +The workings of this sample program should be straightforward if you are +familiar with MIXAL. See TAOCP vol. 1 for a thorough definition or +@ref{MIX and MIXAL tutorial}, for a tutorial. + +@node Compiling, Running the program, Writing a source file, Getting started +@section Compiling +@cindex compiling +@cindex binary programs +@cindex virtual machine +@cindex assembler +@cindex @code{mixasm} + +Three simulators of the MIX computer, called @code{mixvm}, @code{gmixvm} +and @code{mixguile}, are included in the @sc{mdk} tools. They are 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 hello @key{RET} +@end example + +@cindex .mix file + +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. Unless the @code{mixasm} option @code{-O} is provided, the +assembler will 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, Using mixguile, Compiling, Getting started +@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 three software simulators of +the computer, though. They are + +@itemize @bullet +@item +@code{mixvm}, a command line oriented simulator, +@item +@code{gmixvm}, a GTK based graphical interface to @code{mixvm}, and +@item +@code{mixguile}, a Guile shell with a built-in MIX simulator. +@end itemize + +All three simulators accept the same set of user commands, but offer a +different user interface, as noted above. In this section we shall +describe some of these commands, and show you how to use them from +@code{mixvm}'s command line. You can use them as well at @code{gmixvm}'s +command prompt (@pxref{gmixvm}), or using the built-in Scheme primitives +of @code{mixguile} (@pxref{Using mixguile}). + +Using the MIX simulators, 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 to load, run and debug +programs, as well as to inspect 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 +@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@footnote{The device files are stored, by +default, in a directory called @file{.mdk}, which is created in your +home directory the first time @code{mixvm} is run. You can change this +default directory using the command @code{devdir} when running +@code{mixvm} in interactive mode (@pxref{Configuration commands})}. + +The virtual machine can also report the execution time of the program, +according to the (virtual) time spent in each of the binary instructions +(@pxref{Execution times}). Printing of execution time statistics is +activated with the @code{-t} flag; running + +@example +mixvm -t -r hello @key{RET} +@end example + +@noindent +produces the following output: + +@example +MIXAL HELLO WORLD +** Execution time: 11 +@end example + +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 +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@footnote{The @code{mixguile} program allows you to execute +arbitrary combinations of @code{mixvm} commands (using Scheme) +non-interactively. @xref{Scheme scripts}.}. 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}.) + +@cindex @code{load} +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}: + +@cindex @code{pc} +@example +MIX > pc +Current address: 3000 +MIX > +@end example + +@cindex @code{run} +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)@footnote{Printing of timing statistics can be disabled using +the command @code{timing} (@pxref{Configuration commands}).}. 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 + +@cindex @code{pmem} +@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 + +@cindex @code{preg} +@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 + +@cindex @code{help} +@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 + +@cindex @code{next} +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). + +@cindex @code{sbpa} +@cindex breakpoints + +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 + +@cindex @code{sbp} +@cindex breakpoints +@noindent +Note that, since we compiled @file{hello.mixal} with debug info +enabled, 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. You can also set +conditional breakpoints, i.e., tell @code{mixvm} to interrupt program +execution whenever a register, a memory cell, the comparison flag or the +overflow toggle change using the commands @w{@code{sbp[rmco]}} +(@pxref{Debug commands}). + +@cindex @code{psym} +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{strace} (which turns on +tracing of executed intructions), @code{pbt} (which prints a backtrace +of executed instructions) and @code{weval} (which evaluates +w-expressions on the fly). For a complete description of all available +MIX commands, @xref{mixvm}. + +@node Using mixguile, Using Scheme in mixvm and gmixvm, Running the program, Getting started +@section Using @code{mixguile} + +With @code{mixguile} you can run a MIX simulator embedded in a Guile +shell, that is, using Scheme functions and programs. As with +@code{mixvm}, @code{mixguile} can be run both in interactive and +non-interactive modes. The following subsections provide a quick tour on +using this MIX emulator. + +@menu +* The mixguile shell:: Using the Scheme MIX virtual machine. +* Additional functions:: Scheme functions accessing the VM. +* Defining new functions:: Defining your own Scheme functions. +* Hook functions:: Using command and break hook functions. +* Scheme scripts:: +@end menu + +@node The mixguile shell, Additional functions, Using mixguile, Using mixguile +@subsection The @code{mixguile} shell +@cindex Scheme +@cindex @code{mixguile} +@cindex REPL + +If you simply type + +@example +mixguile @key{RET} +@end example +@noindent +at the command prompt, you'll be presented a Guile shell prompt like +this + +@example +guile> +@end example +@noindent +At this point, you have entered a Scheme read-eval-print loop (REPL) +which offers you all the Guile functionality plus a new set of built-in +procedures to execute and debug MIX programs. Each of the @code{mixvm} +commands described in the previous sections (and in @pxref{mixvm}) have +a Scheme function counterpart named after it by prepending the prefix +@code{mix-} to its name. Thus, to load our hello world program, you can +simply enter + +@example +guile> (mix-load "hello") +Program loaded. Start address: 3000 +guile> +@end example +@noindent +and run it using @code{mix-run}: + +@example +guile> (mix-run) +Running ... +MIXAL HELLO WORLD +... done +Elapsed time: 11 /Total program time: 11 (Total uptime: 11) +guile> +@end example +@noindent +In the same way, you can execute it step by step using the Scheme +function @code{mix-next} or set a breakpoint: + +@example +guile> (mix-sbp 4) +Breakpoint set at line 5 +guile> +@end example +@noindent +or, if you one to peek at a register contents: + +@example +guile> (mix-preg 'A) +rA: + 00 00 00 00 00 (0000000000) +guile> +@end example + +You get the idea: you have at your disposal all the @code{mixvm} and +@code{gmixvm} commands by means of @code{mix-} functions. But, in case +you are wondering, this is only the beginning. You also have at your +disposal a whole Scheme interpreter, and you can, for instance, define +new functions combining the @code{mix-} and all other Scheme +primitives. In the next sections, you'll find examples of how to take +advantage of the Guile interpreter. + +@node Additional functions, Defining new functions, The mixguile shell, Using mixguile +@subsection Additional MIX Scheme functions + +The @code{mix-} function counterparts of the @code{mixvm} commands don't +return any value, and are evaluated only for their side-effects +(possibly including informational messages to the standard output and/or +error stream). When writting your own Scheme functions to manipulate the +MIX virtual machine within @code{mixguile} (@pxref{Defining new +functions}), you'll probably need Scheme functions returning the value +of the registers, memory cells and so on. Don't worry: @code{mixguile} +also offers you such functions. For instance, to access the (numerical) +value of a register you can use @code{mix-reg}: + +@example +guile> (mix-reg 'I2) +0 +guile> +@end example +@noindent +Note that, unlike @code{(mix-preg 'I2)}, the expression @code{(mix-reg +'I2)} in the above example evaluates to a Scheme number and does not +produce any side-effect: + +@example +guile> (number? (mix-reg 'I2)) +#t +guile> (number? (mix-preg 'I2)) +rI2: + 00 00 (0000) +#f +guile> +@end example + +In a similar fashion, you can access the memory contents using +@code{(mix-cell)}, or the program counter using @code{(mix-loc)}: + +@example +guile> (mix-cell 3000) +786957541 +guile> (mix-loc) +3002 +guile> +@end example + +Other functions returning the contents of the virtual machine components +are @code{mix-cmp} and @code{mix-over}, which eval to the value of the +comparison flag and the overflow toggle respectively. For a complete +list of these additional functions, @xref{mixguile}. + +In the next section, we'll see a sample of using these functions to +extend @code{mixguile}'s functionality. + +@node Defining new functions, Hook functions, Additional functions, Using mixguile +@subsection Defining new functions +@cindex Scheme functions + +Scheme is a powerful language, and you can use it inside @code{mixguile} +to easily extend the MIX interpreter's capabilities. For example, you +can easily define a function that loads a file, prints its name, +executes it and, finally, shows the registers contents, all in one shot: + +@example +guile> (define my-load-and-run @key{RET} + (lambda (file) @key{RET} + (mix-load file) @key{RET} + (display "File loaded: ") @key{RET} + (mix-pprog) @key{RET} + (mix-run) @key{RET} + (mix-preg))) @key{RET} +guile> +@end example +@noindent +and use it to run your programs: + +@example +guile> (my-load-and-run "hello") +Program loaded. Start address: 3000 +File loaded: hello.mix +Running ... +MIXAL HELLO WORLD +... done +Elapsed time: 11 /Total program time: 11 (Total uptime: 33) +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) +guile> +@end example + + +Or, maybe, you want a function which sets a breakpoint at a specified +line number before executing it: + +@example +guile> (define my-load-and-run-with-bp + (lambda (file line) + (mix-load file) + (mix-sbp line) + (mix-run))) +guile> (my-load-and-run-with-bp "samples/primes" 10) +Program loaded. Start address: 3000 +Breakpoint set at line 10 +Running ... +... stopped: breakpoint at line 10 (address 3001) +Elapsed time: 1 /Total program time: 1 (Total uptime: 45) +guile> +@end example + +As a third example, the following function loads a program, runs it and +prints the contents of the memory between the program's start and end +addresses: + +@example +guile> (define my-run + (lambda (file) + (mix-load file) + (let ((start (mix-loc))) + (mix-run) + (mix-pmem start (mix-loc))))) +guile> (my-run "hello") +Program loaded. Start address: 3000 +Running ... +MIXAL HELLO WORLD +... done +Elapsed time: 11 /Total program time: 11 (Total uptime: 11) +3000: + 46 58 00 19 37 (0786957541) +3001: + 00 00 00 02 05 (0000000133) +3002: + 14 09 27 01 13 (0237350989) +guile> +@end example + + +As you can see, the possibilities are virtually unlimited. Of course, +you don't need to type a function definition each time you start +@code{mixguile}. You can write it in a file, and load it using Scheme's +@code{load} function. For instance, you can create a file named, say, +@file{functions.scm} with your definitions (or any Scheme expression) +and load it at the @code{mixguile} prompt: + +@example +guile> (load "functions.scm") +@end example + +Alternatively, you can make @code{mixguile} to load it for you. When +@code{mixguile} starts, it looks for a file named @file{mixguile.scm} in +your MDK configuration directory (@file{~/.mdk}) and, if it exists, +loads it before entering the REPL. Therefore, you can copy your +definitions in that file, or load the @file{functions.scm} file in +@file{mixguile.scm}. + +@node Hook functions, Scheme scripts, Defining new functions, Using mixguile +@subsection Hook functions +@cindex hook function +@cindex pre-hook +@cindex post-hook + +Hooks are functions called before or after a given event occurs. In +@code{mixguile}, you can define command and break hooks, which are +associated, respectively, with command execution and program +interruption events. The following sections give you a tutorial on using +hook functions within @code{mixguile}. + +@menu +* Command hooks:: +* Break hooks:: +@end menu + +@node Command hooks, Break hooks, Hook functions, Hook functions +@subsubsection Command hooks + +In the previous section, we have seen how to extend @code{mixguile}'s +functionality through the use of user defined functions. Frequently, +you'll write new functions that improve in some way the workings of a +built-in @code{mixvm} command, following this pattern: + +@enumerate a +@item +Prepare the command execution +@item +Execute the desired command +@item +Perform post execution operations +@end enumerate + +We call the functions executed in step (a) @dfn{pre-hook}s, and those of +step @dfn{post-hook}s of the given command. @code{mixguile} lets you +specify pre- and post-hooks for any @code{mixvm} command using the +@code{mix-add-pre-hook} and @code{mix-add-post-hook} functions, which +take as arguments a symbol naming the command and a function to be +executed before (resp. after) the command. In other words, +@code{mixguile} will execute for you steps (a) and (c) above whenever +you eval (b). The hook functions must take a single argument, which is a +string list of the command's arguments. As an example, let us define the +following hooks for the @code{next} command: + +@example +(define next-pre-hook + (lambda (arglist) + (mix-slog #f))) + +(define next-post-hook + (lambda (arglist) + (display "Stopped at line ") + (display (mix-src-line-no)) + (display ": ") + (display (mix-src-line)) + (newline) + (mix-slog #t))) +@end example +@noindent +In these functions, we are using the function @code{mix-slog} to turn +off the informational messages produced by the virtual machine, since we +are providing our own ones in the post hook function. To install these +hooks, we would write: + +@example +(mix-add-pre-hook 'next next-pre-hook) +(mix-add-post-hook 'next next-post-hook) +@end example +@noindent +Assuming we have put the above expressions in @code{mixguile}'s +initialisation file, we would obtain the following results when +evaluating @code{mix-next}: + +@example +guile> (mix-next) +MIXAL HELLO WORLD +Stopped at line 6: HLT +guile> +@end example + +As a second, more elaborated, example, let's define hooks which print +the address and contents of a cell being modified using @code{smem}. The +hook functions could be something like this: + +@example +(define smem-pre-hook + (lambda (arglist) + (if (eq? (length arglist) 2) + (begin + (display "Changing address ") + (display (car arglist)) + (newline) + (display "Old contents: ") + (display (mix-cell (string->number (car arglist)))) + (newline)) + (error "Wrong arguments" arglist)))) + +(define smem-post-hook + (lambda (arglist) + (if (eq? (length arglist) 2) + (begin + (display "New contents: ") + (display (mix-cell (string->number (car arglist)))) + (newline))))) +@end example +@noindent +and we can install them using + +@example +(mix-add-pre-hook 'smem smem-pre-hook) +(mix-add-post-hook 'smem smem-post-hook) +@end example +@noindent +Aferwards, a sample execution of @code{mix-smem} would look like this: + +@example +guile> (mix-smem 2000 100) +Changing address 2000 +Old contents: 0 +New contents: 100 +guile> +@end example + +@cindex global hook + +You can add any number of hooks to a given command. They will be +executed in the same order as they are registered. You can also define +global post (pre) hooks, which will be called before (after) any +@code{mixvm} command is executed. Global hook functions must admit two +arguments, namely, a string naming the invoked command and a string list +of its arguments, and they are installed using the Scheme functions +@code{mix-add-global-pre-hook} and @code{mix-add-global-post-hook}. A +simple example of global hook would be: + +@example +guile> (define pre-hook + (lambda (cmd args) + (display cmd) + (display " invoked with arguments ") + (display args) + (newline))) +guile> (mix-add-global-pre-hook pre-hook) +ok +guile> (mix-pmem 120 125) +pmem invoked with arguments (120-125) +0120: + 00 00 00 00 00 (0000000000) +0121: + 00 00 00 00 00 (0000000000) +0122: + 00 00 00 00 00 (0000000000) +0123: + 00 00 00 00 00 (0000000000) +0124: + 00 00 00 00 00 (0000000000) +0125: + 00 00 00 00 00 (0000000000) +guile> +@end example + +Note that if you invoke @code{mixvm} commands within a global hook, its +associated command hooks will be run. Thus, if you have installed both +the @code{next} hooks described earlier and the global hook above, +executing @code{mix-next} will yield the following result: + +@example +guile> (mix-next 5) +next invoked with arguments (5) +slog invoked with arguments (off) +MIXAL HELLO WORLD +Stopped at line 7: MSG ALF "MIXAL" +slog invoked with arguments (on) +guile> +@end example + +Adventurous readers may see the above global hook as the beginning of a +command log utility or a macro recorder that saves your commands for +replay. + +@node Break hooks, , Command hooks, Hook functions +@subsubsection Break hooks + +@cindex break hook + +We have seen in the previous section how to associate hooks to command +execution, but they are not the whole story. You can also associate hook +functions to program interruption, that is, specify functions that +should be called every time the execution of a MIX program is stopped +due to the presence of a breakpoint, either explicit or +conditional. Break hooks take as arguments the line number and memory +address at which the break occurred. A simple hook that logs the line +and address of the breakpoint could be defined as: + +@example +(define break-hook + (lambda (line address) + (display "Breakpoint encountered at line ") + (display line) + (display " and address ") + (display address) + (newline))) +@end example +@noindent +and installed for explicit and conditional breakpoints using + +@example +(mix-add-break-hook break-hook) +(mix-add-cond-break-hook break-hook) +@end example +@noindent +after that, every time the virtual machine encounters a breakpoint, +@code{break-code} shall be evaluated for you@footnote{You may have +noticed that break hooks can be implemented in terms of command hooks +associated to @code{mix-run} and @code{mix-next}. As a matter of fact, +they @emph{are} implemented this way: take a look at the file +@file{@emph{install_dir}/share/mdk/mix-vm-stat.scm} if you are curious.}. + +@node Scheme scripts, , Hook functions, Using mixguile +@subsection Scheme scripts +@cindex Scheme script +@cindex non-interactive + +Another useful way of using @code{mixguile} is writing executable +scripts that perform a set of commands for you. This is done using the +@code{mixguile} switch @code{-s} (being a Guile shell, @code{mixguile} +accepts all the command options of @code{guile}; type @code{mixguile -h} +for a list of all available command options). For instance, if you have +a very useful MIX program @file{foo.mix} which you want to run often, +you don't have to fire a MIX virtual machine, load and run it every +time; you can write a Scheme script instead: + +@example +#! /usr/bin/mixguile -s +!# +;;; runprimes: execute the primes.mix program + +;; load the file you want to run +(mix-load "../samples/primes") +;; execute it +(mix-run) +;; print the contents of registers +(mix-pall) +;; ... +@end example + +Just save the above script to a file named, say, @file{runtest}, make it +executable (@code{chmod +x runtest}), and, well, execute it from the +Unix shell: + +@example +$ ./runtest +Program loaded. Start address: 3000 +Running ... +... done +Elapsed time: 190908 /Total program time: 190908 (Total uptime: 190908) +rA: + 30 30 30 30 30 (0511305630) +rX: + 30 30 32 32 39 (0511313959) +rJ: + 47 18 (3026) +rI1: + 00 00 (0000) rI2: + 55 51 (3571) +rI3: + 00 19 (0019) rI4: + 31 51 (2035) +rI5: + 00 00 (0000) rI6: + 00 00 (0000) +Overflow: F +Cmp: L +$ +@end example + +Note that this is far more flexible that running programs +non-interactively using @code{mixvm} (@pxref{Non-interactive mode}), for +you can execute any combination of commands you want from a Scheme +script (not just running and dumping the registers). For additional +@code{mixguile} command line options, see @ref{Invoking mixguile}. + +@node Using Scheme in mixvm and gmixvm, , Using mixguile, Getting started +@section Using Scheme in @code{mixvm} and @code{gmixvm} +@cindex @code{scmf} + +In the previous section (@pxref{Using mixguile}) we have seen how the +Guile shell @code{mixguile} offers you the possibility of using Scheme +to manipulate a MIx virtual machine and extend the set of commands +offered by @code{mixvm} and @code{gmixvm}. This possibility is not +limited to the @code{mixguile} shell. Actually, both @code{mixvm} and +@code{gmixvm} incorporate an embedded Guile interpreter, and can +evaluate Scheme expressions. To evaluate a single-line expression at the +@code{mixvm} or @code{gmixvm} command prompt, simply write it and press +return (the command parser will recognise it as a Scheme expression +because it is parenthesized, and will pass it to the Guile +interpreter). A sample @code{mixvm} session using Scheme expressions +could be: + +@example +MIX > load hello +Program loaded. Start address: 3000 +MIX > (define a (mix-loc)) +MIX > run +Running ... +MIXAL HELLO WORLD +... done +Elapsed time: 11 /Total program time: 11 (Total uptime: 11) +MIX > (mix-pmem a) +3000: + 46 58 00 19 37 (0786957541) +MIX > (mix-pmem (mix-loc)) +3002: + 14 09 27 01 13 (0237350989) +MIX > +@end example + +You can also load and evaluate a file, using the @code{scmf} +command like this: + +@example +MIX> scmf /path/to/file/file.scm +@end example + +Therefore, you have at your disposal all the @code{mixguile} goodies +described above (new functions, new command definitions, hooks...) +inside @code{mixvm} and @code{gmixvm}. In other words, these programs +are extensible using Scheme. See @ref{Using mixguile} for examples of +how to do it. + diff --git a/doc/mdk_index.texi b/doc/mdk_index.texi new file mode 100644 index 0000000..68f3c48 --- /dev/null +++ b/doc/mdk_index.texi @@ -0,0 +1,14 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_index.texi,v 1.7 2004/08/03 13:23:06 jao Exp $ + +@node Concept Index, Instructions and commands, Copying, Top +@unnumbered Concept Index + +@cindex tail recursion +@printindex cp + diff --git a/doc/mdk_install.texi b/doc/mdk_install.texi new file mode 100644 index 0000000..08a44e2 --- /dev/null +++ b/doc/mdk_install.texi @@ -0,0 +1,287 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@node Installing MDK, MIX and MIXAL tutorial, Acknowledgments, Top +@comment node-name, next, previous, up +@chapter Installing @sc{mdk} + +@menu +* Download:: +* Requirements:: +* Basic installation:: +* Emacs support:: +* Special configure flags:: +* Supported platforms:: +@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} +@item +@uref{http://www.gnu.org/prep/ftp.html, GNU 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{https://savannah.gnu.org/cvs/?group_id=118} +@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 2.4.0} (required) +@item +@uref{http://www.gnu.org/software/flex/flex.html, GNU Flex 2.5} (required) +@item +@uref{http://www.gtk.org, GTK 2.4.0} (optional) +@item +@uref{http://ftp.gnome.org/pub/GNOME/sources/libglade/2.4/, Libglade +2.4.0} +(optional) +@item +@uref{http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html, GNU +Readline} +(optional) +@item +@uref{http://www.gnu.org/software/guile, GNU Libguile 1.6} (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}. Finally, if +libguile is found, the @sc{mdk} utilities will be compiled with Guile +support and will be extensible using Scheme. + +@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{libgtk2.0-0} and @file{libgtk2.0-0-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 1.2 has been successfully configured. *** + +Type 'make' to build the following utilities: + - mixasm (MIX assembler) + - mixvm (MIX virtual machine, with readline support, + with guile support) + - gmixvm (mixvm GTK+ GUI, with guile support) + - mixguile (the mixvm guile shell) +@end example + +@noindent +where the last lines 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} +@item +@file{mixguile/mixguile} +@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 + +@sc{mdk} includes extensive support for Emacs. Upon installation, all +the elisp code is installed in @file{PREFIX/share/mdk}, where +@file{PREFIX} stands for your installation root directory (e.g. +@file{/usr/local}). You can copy the elisp files to a directory that +is in your load-path, or you can add the above directory to it. +Assuming that the installing prefix is @file{/usr/local}, +you can do it by adding to your @file{.emacs} file the following line: + +@lisp +(setq load-path (cons "/usr/local/share/mdk" load-path)) +@end lisp + +@code{MIXAL} programs can be written using Emacs and the elisp program +@file{share/mdk/mixal-mode.el}, contributed by @value{PIETER}. It +provides font locking, interactive help, compiling assistance and +invocation of the @code{MIX} virtual machine via a new major mode +called @code{mixal-mode}. To start @code{mixal-mode} automatically +whenever you edit a @code{MIXAL} source file, add the following lines +to your @file{.emacs} file: + +@lisp +(autoload 'mixal-mode "mixal-mode" t) +(add-to-list 'auto-mode-alist '("\\.mixal\\'" . mixal-mode)) +@end lisp + +In addition, @code{mixvm} can be run within an Emacs @acronym{GUD} +buffer using the elisp program @file{share/mdk/mixvm.el}, 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, Supported platforms, Emacs support, Installing MDK +@comment node-name, next, previous, up +@section Special configure flags + +You can fine-tune the configuration process using the following +switches with configure: + +@defopt @w{--enable-gui[=yes|no]} +@defoptx --disable-gui +Enables/disables the build 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 @w{--with-guile[=yes|no]} +@defoptx --without-guile +Enables/disables the Guile support for @code{mixvm} and @code{gmixvm}, +and the build of @code{mixguile}. If the +required libraries are missing (@pxref{Requirements}) the configure +script with automatically disable this feature. +@end defopt + +@defopt @w{--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 + +@node Supported platforms, , Special configure flags, Installing MDK +@comment node-name, next, previous, up +@section Supported platforms + +GNU MDK has been tested in the following platforms: + +@itemize +@item +Debian GNU/Linux 2.2, 2.3, 3.0, 3.1, 3.2 +@item +Redhat GNU/Linux 8.0 (Ronald Cole), 7.0 (Agustin Navarro), 6.2 +(Roberto Ferrero) +@item +Mandrake 8.0 (Agustin Navarro) +@item +FreeBSD 4.2, 4.3, 4.4, 4.5 (Ying-Chieh Liao), 5.2 +@item +Solaris 2.8/gcc 2.95.3 (Stephen Ramsay) +@item +MS Windows 98 SE/Cygwin 1.1.8-2 (Christoph von +Nathusius)@footnote{Caveats: Christoph has only tested @code{mixvm} and +@code{mixasm} on this platform, using @code{gcc} 2.95.3-2, @code{GLIB} +1.2.10 and @code{GNUreadline} 4.1-2. He has reported missing history +functionalities on a first try. If you find problems with +history/readline functionality, please try a newer/manually installed +readline version.} +@item +Mac OS X 10.1.2 (Johan Swanljung) +@item +AMD Athlon, GNU/Linux version 2.4.2-2smp (Red Hat 7.1 (Seawolf)) (N. +H. F. Beebe) +@item +Apple PowerPC G3, GNU/Linux 2.2.18-4hpmac (Red Hat Linux/PPC +2000 Q4) (N. H. F. Beebe) +@item +DEC Alpha, GNU/Linux 2.2.19-6.2.1 (Red Hat 6.2) (N. H. F. Beebe) +@item +Compaq/DEC Alpha OSF/1 4.0F [ONLY after adding rsync's snprintf() +implementation] (N. H. F. Beebe) +@item +IBM PowerPC AIX 4.2 (N. H. F. Beebe) +@item +Intel Pentium III, GNU/Linux 2.4.9-31smp (Red Hat 7.2 (Enigma)) (N. H. +F. Beebe) +@item +SGI Origin 200, IRIX 6.5 (N. +H. F. Beebe) +@item +Sun SPARC, GNU/Linux 2.2.19-6.2.1 (Red Hat 6.2) (N. H. F. Beebe) +@item +Sun SPARC, Solaris 2.8 (N. H. F. Beebe) +@end itemize + +@sc{mdk} will probably work on any GNU/Linux or BSD platform. If you +try it in a platform not listed above, please send a mail to +@email{jao@@gnu.org, the author}. + + + + diff --git a/doc/mdk_intro.texi b/doc/mdk_intro.texi new file mode 100644 index 0000000..b4ce2ad --- /dev/null +++ b/doc/mdk_intro.texi @@ -0,0 +1,70 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_intro.texi,v 1.8 2004/08/03 13:23:06 jao Exp $ + +@node Introduction, Acknowledgments, 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}, @code{mixguile} +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 mixguile +A Guile shell, with an embedded MIX virtual machine and built-in +commands to manipulate it using Scheme. +@item mixal-mode.el +An Emacs major mode for MIXAL source files editing, providing syntax +highlighting, documentation lookup and invocation of @code{mixvm} +within Emacs. +@item mixvm.el +This elisp program allows running @code{mixvm} inside an Emacs GUD +buffer, providing 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}. On the other hand, @code{mixguile} offers you +the possibility of manipulating a MIX virtual machine through a set of +Scheme functions, so that you can use this programming language to +interact with the virtual machine. In addition, @code{mixvm} and +@code{gmixvm} are also able to interpret Scheme scripts (using an +embedded Guile interpreter), that is, you can use Scheme as an extension +language to add new functionalities to these programs. + +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..fa144a7 --- /dev/null +++ b/doc/mdk_mixasm.texi @@ -0,0 +1,89 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_mixasm.texi,v 1.10 2004/08/05 21:32:46 jao Exp $ + +@node mixasm, mixvm, Emacs tools, 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 mixasm:: +@end menu + +@node Invoking 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 [-vhulO] [-o OUTPUT_FILE] [--version] [--help] [--usage] + [--ndebug] [--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 -O +@defoptx --ndebug +Do not include debugging information in the compiled file, saving +space but disallowing 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 @w{--list[=list_file]} +@cindex .mls 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_mixguile.texi b/doc/mdk_mixguile.texi new file mode 100644 index 0000000..2d6ac65 --- /dev/null +++ b/doc/mdk_mixguile.texi @@ -0,0 +1,445 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_mixguile.texi,v 1.5 2004/08/03 13:23:06 jao Exp $ + +@node mixguile, Problems, gmixvm, Top +@chapter @code{mixguile}, the Scheme virtual machine +@cindex @code{mixguile} + +This chapter provides a reference to using @code{mixguile} and the +Scheme function library giving access to the MIX virtual machine in the +@sc{mdk} emulators (@code{mixguile}, @code{mixvm} and @code{gmixvm}). See +@ref{Using mixguile} for a tutorial, step by step introduction to +@code{mixguile} and using Scheme as an extension language for the +@sc{mdk} MIX virtual machines. + +@menu +* Invoking mixguile:: Command line options. +* Scheme functions reference:: Scheme functions accessing the VM. +@end menu + +@node Invoking mixguile, Scheme functions reference, mixguile, mixguile +@section Invoking @code{mixguile} +@cindex @code{mixguile} options + +Invoking @code{mixguile} without arguments will enter the Guile REPL +(read-eval-print loop) after loading, if it exists, the user's +initialisation file (@file{~/.mdk/mixguile.scm}). + +@code{mixguile} accepts the same command line options than Guile: + +@example +mixguile [-s SCRIPT] [-c EXPR] [-l FILE] [-e FUNCTION] [-qhv] + [--help] [--version] +@end example + +The meaning of these options is as follows: + +@defopt -h +@defoptx --help +Prints usage summary and exits. +@end defopt + +@defopt -v +@defoptx --version +Prints version and copyleft information and exits. +@end defopt + +@defopt -s SCRIPT +Loads Scheme code from @var{script}, evaluates it and exits. This option +can be used to write executable Scheme scripts, as described in +@ref{Scheme scripts}. +@end defopt + +@defopt -c EXPR +Evaluates the given Scheme expression and exits. +@end defopt + +@defopt -l FILE +Loads the given Scheme file and enters the REPL (read-eval-print loop). +@end defopt + +@defopt -e FUNCTION +After reading the script, executes the given function using the provided +command line arguments. For instance, you can write the following Scheme +script: + +@example +#! /usr/bin/mixguile \ +-e main -s +!# + +;;; execute a given program and print the registers. + +(define main + (lambda (args) + ;; load the file provided as a command line argument + (mix-load (cadr args)) + ;; execute it + (mix-run) + ;; print the contents of registers + (mix-pall))) + +@end example +@noindent +save it in a file called, say, @file{foo}, make it executable, and run +it as + +@example +$ ./foo hello +@end example +@noindent +This invocation will cause the evaluation of the @code{main} function +with a list of command line parameters as its argument (@code{("./foo" +"hello")} in the above example. Note that command line options to +mixguile must be written in their own line after the @code{\} symbol. +@end defopt + +@defopt -q +Do not load user's initialisation file. When @code{mixguile} starts up, +it looks for a file named @file{mixguile.scm} in the user's @sc{mdk} +configuration directory (@file{~/.mdk}), and loads it if it exists. This +option tells @code{mixguile} to skip this initialisation file loading. +@end defopt + + +@node Scheme functions reference, , Invoking mixguile, mixguile +@section Scheme functions reference + +As we have previously pointed out, @code{mixguile} embeds a MIX virtual +machine that can be accessed through a set of Scheme functions, that is, +of a Scheme library. Conversely, @code{mixvm} and @code{gmixvm} contain +a Guile interpreter, and are able to use this same Scheme library, as +well as all the other Guile/Scheme primitives and any user defined +function. Therefore, you have at your disposal a powerful programming +language, Scheme, to extend the @sc{mdk} virtual machine emulators (see +@ref{Using Scheme in mixvm and gmixvm} for samples of how to do it). + +The following subsections describe available functions the MIX/Scheme +library. + +@menu +* mixvm wrappers:: Functions invoking mixvm commands. +* Hooks:: Adding hooks to mixvm commands. +* Additional VM functions:: Functions accessing the MIX virtual machine. +@end menu + +@node mixvm wrappers, Hooks, Scheme functions reference, Scheme functions reference +@subsection @code{mixvm} command wrappers + +For each of the @code{mixvm} commands listed in @ref{Commands}, there is +a corresponding Scheme function named by prefixing the command name with +@code{mix-} (e.g., @code{mix-load}, @code{mix-run} and so on). These +command wrappers are implemented using a generic command dispatching +function: + +@defun mixvm-cmd command argument +Dispatchs the given @var{command} to the MIX virtual appending the +provided @var{argument}. Both @var{command} and @code{argument} must be +strings. The net result is as writing "@var{command} @var{argument}" at +the @code{mixvm} or @code{gmixvm} command prompt. +@end defun + +For instance, you can invoke the @code{run} command at the @code{mixvm} +prompt in three equivalent ways: + +@example +MIX > run hello +MIX > (mix-run "hello") +MIX > (mixvm-cmd "run" "hello") +@end example +@noindent +(only the two last forms can be used at the @code{mixguile} prompt or +inside a Scheme script). + +The @code{mix-} functions evaluate to a unspecified value. If you want +to check the result of the last @code{mixvm} command invocation, use the +@code{mix-last-result} function: + +@defun mix-last-result +Returns @var{#t} if the last @code{mixvm} command invocation was +successful, @var{#f} otherwise. +@end defun +@noindent +Using this function, we could improve the script for running a program +presented in the previous section by adding error checking: + + +@example +#! /usr/bin/mixguile \ +-e main -s +!# + +;;; Execute a given program and print the registers. + +(define main + (lambda (args) + ;; load the file provided as a command line argument + (mix-load (cadr args)) + ;; execute it if mix-load succeeded + (if (mix-last-result) (mix-run)) + ;; print the contents of registers if the above commands succeded + (if (mix-last-result) (mix-pall)))) +@end example + +Please, refer to @ref{Commands} for a list of available commands. Given +the description of a @code{mixvm}, it is straightforward to use its +Scheme counterpart and, therefore, we shall not give a complete +description of these functions here. Instead, we will only mention those +wrappers that exhibit a treatment of their differing from that of their +command counterpart. + +@defun mix-preg [register] +@defunx mix-sreg register value +The argument @var{register} of these functions can be either a string or +a symbol representing the desired register. For instance, the following +invocations are equivalent: + +@example +(mix-preg 'I1) +(mix-preg "I1") +@end example +@end defun + +@defun mix-pmem from [to] +The command @code{pmem} takes a single argument which can be either a +cell number or a range of the form @code{FROM-TO}. This function takes +one argument to ask for a single memory cell contents, or two parameters +to ask for a range. For instance, the following commands are equivalent: + +@example +MIX > pmem 10-12 +0010: + 00 00 00 00 00 (0000000000) +0011: + 00 00 00 00 00 (0000000000) +0012: + 00 00 00 00 00 (0000000000) +MIX > (mix-pmem 10 12) +0010: + 00 00 00 00 00 (0000000000) +0011: + 00 00 00 00 00 (0000000000) +0012: + 00 00 00 00 00 (0000000000) +MIX > +@end example +@end defun + +@defun mix-sover #t|#f +The command @code{sover} takes as argument either the string @code{T} or +the string @code{F}, to set, respectively, the overflow toggle to true +or false. Its Scheme counterpart, @code{mix-sover}, takes as argument +a Scheme boolean value: @code{#t} (true) or @code{#f}. +@end defun + +For the remaining functions, you simply must take into account that when +the command arguments are numerical, the corresponding Scheme function +takes as arguments Scheme number literals. On the other hand, when the +command argument is a string, the argument of its associated Scheme +function will be a Scheme string. By way of example, the following +invocations are pairwise equivalent: + +@example +MIX > load ../samples/hello +MIX > (mix-load "../samples/hello") + +MIX > next 5 +MIX > (mix-next 5) +@end example + +@node Hooks, Additional VM functions, mixvm wrappers, Scheme functions reference +@subsection Hook functions + +Hooks are functions evaluated before or after executing a @code{mixvm} +command (or its corresponding Scheme function wrapper), or after an +explicit or conditional breakpoint is found during the execution of a +MIX program. The following functions let you install hooks: + +@defun mix-add-pre-hook command hook +Adds a function to the list of pre-hooks associated with the give +@var{command}. @var{command} is a string naming the corresponding @code{mixvm} +command, and @var{hook} is a function which takes a single argument: a +string list of the commands arguments. The following scheme code defines +a simple hook and associates it with the @code{run} command: + +@example +(define run-hook + (lambda (args) + (display "argument list: ") + (display args) + (newline))) +(mix-add-pre-hook "run" run-hook) +@end example + +Pre-hooks are executed, in the order they are added, before invoking the +corresponding command (or its associated Scheme wrapper function). +@end defun + +@defun mix-add-post-hook command hook +Adds a function to the list of pre-hooks associated with the give +@var{command}. The arguments have the same meaning as in +@code{mix-add-pre-hook}. +@end defun + +@defun mix-add-global-pre-hook hook +@defunx mix-add-global-post-hook hook +Global pre/post hooks are executed before/after any @code{mixvm} command +or function wrapper invocation. In this case, @var{hook} takes two +arguments: a string with the name of the command being invoked, and a +string list with its arguments. +@end defun + +@defun mix-add-break-hook hook +@defunx mix-add-cond-break hook +Add a hook funtion to be executed when an explicit (resp. conditional) +breakpoint is encountered during program execution. @var{hook} is a +function taking two arguments: the source line number where the hook has +occurred, and the current program counter value. The following code +shows a simple definition and installation of a break hook: + +@example +(define break-hook + (lambda (line address) + (display "Breakpoint at line ") (display line) + (display " and address ") (display address) + (newline))) +(mix-add-break-hook break-hook) +@end example + +Break hook functions are entirely implemented in Scheme using regular +post-hooks for the @code{next} and @code{run} commands. If you are +curious, you can check the Scheme source code at +@file{@emph{prefix}/share/mdk/mixguile-vm-stat.scm} (where @emph{prefix} +stands for your root install directory, usualy @code{/usr} or +@code{/usr/local}. +@end defun + + +See @ref{Hook functions} for further examples on using hook functions. + + +@node Additional VM functions, , Hooks, Scheme functions reference +@subsection Additional VM functions + +When writing non-trivial Scheme extensions using the MIX/Scheme library, +you will probably need to evaluate the contents of the virtual machine +components (registers, memory cells and so on). For instance, you may +need to store the contents of the @code{A} register in a variable. The +Scheme functions described so far are of no help: you can print the +contents of @code{A} using @code{(mix-preg 'A)}, but you cannot define a +variable containing the contents of @code{A}. To address this kind of +problems, the MIX/Scheme library provides the following additional +functions: + +@defun mixvm-status +@defunx mix-vm-status +Return the current status of the virtual machine, as a number +(@code{mixvm-status}) or as a symbol (@code{mix-vm-status}). Posible +return values are: +@multitable {aamixvmaastatusaa} {aamixvmastatusaaaaaaa} {return valuesaaaaaaaaaaaaaaaaaaaaaaaaaa} +@item @code{(mixvm-status)} @tab @code{(mix-vm-status)} @tab +@item 0 @tab MIX_ERROR @tab Loading or execution error +@item 1 @tab MIX_BREAK @tab Breakpoint encountered +@item 2 @tab MIX_COND_BREAK @tab Conditional breakpoint +@item 3 @tab MIX_HALTED @tab Execution terminated +@item 4 @tab MIX_RUNNING @tab Execution stopped after @code{next} +@item 5 @tab MIX_LOADED @tab Program successfully loaded +@item 6 @tab MIX_EMPTY @tab No program loaded +@end multitable +@end defun + +@defun mix-vm-error? +@defunx mix-vm-break? +@defunx mix-vm-cond-break? +@defunx mix-vm-halted? +@defunx mix-vm-running? +@defunx mix-vm-loaded? +@defunx mix-vm-empty? +Predicates asking whether the current virtual machine status is +@code{MIX_ERROR}, @code{MIX_BREAK}, etc. +@end defun + +@defun mix-reg register +@defunx mix-set-reg! register value +@code{mix-reg} evaluates to a number which is the contents of the +specified @var{register}. @code{mix-set-reg} sets the contents of the +given @var{register} to @var{value}. The register can be specified +either as a string (@code{"A"}, @code{"X"}, etc.) or as a symbol +(@code{'A}, @code{'X}, etc.). For instance, + +@example +guile> (mix-reg 'A) +2341 +guile> (mix-set-reg! "A" 2000) +ok +guile> (define reg-a (mix-reg 'A)) +guile> (display reg-a) +2000 +guile> +@end example +@end defun + +@defun mix-cell cell_no +@defunx mix-set-cell! cell_no value +Evaluate and set the contents of the memory cell number +@var{cell_no}. Both @var{cell_no} and @var{value} are Scheme numbers. +@end defun + +@defun mix-loc +Evaluates to the value of the location counter (i.e., the address of the +next instruction to be executed). +@end defun + +@defun mix-over +@defunx mix-set-over! #t|#f +@code{mix-over} evaluates to @code{#t} if the overflow toggle is set, +and to @code{#f} otherwise. The value of the overflow toggle can be +modified using @code{mix-set-over!}. +@end defun + +@defun mix-cmp +@defunx mix-set-cmp! 'L|'E|'G +Evaluate and set the comparison flag. Possible values are the scheme +symbols @code{L} (lesser), @code{E} (equal) and @code{G} (greater). +@end defun + +@defun mix-up-time +Evaluates to the current virtual machine uptime. +@end defun + +@defun mix-lap-time +Evaluates to the current virtual machine lapsed time, i.e., the time +elapsed since the last @code{run} or @code{next} command. +@end defun + +@defun mix-prog-time +Evaluates to the total time spent executing the currently loaded program. +@end defun + +@defun mix-prog-name +Evaluates to a string containing the basename (without any leading path) +of the currently loaded MIX program. +@end defun + +@defun mix-prog-path +Evaluates to a string containing the full path to the currently loaded +MIX program. +@end defun + +@defun mix-src-path +Evaluates to a string containing the full path to the source file of the +currently loaded MIX program. +@end defun + +@defun mix-src-line [lineno] +@defunx mix-src-line-no +@code{mix-src-line-no} evaluates to the current source file number +during the execution of a program. @code{mix-src-line} evaluates to a +string containing the source file line number @var{lineno}; when +invoked without argument, it evaluates to @code{(mix-src-line +(mix-src-line-no))}. +@end defun + +@defun mix-ddir +Evaluates to a string containing the full path of the current device +directory. +@end defun diff --git a/doc/mdk_mixvm.texi b/doc/mdk_mixvm.texi new file mode 100644 index 0000000..2e21289 --- /dev/null +++ b/doc/mdk_mixvm.texi @@ -0,0 +1,813 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_mixvm.texi,v 1.20 2005/09/19 21:29:42 jao Exp $ + +@node mixvm, gmixvm, mixasm, 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:: +* 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 [-vhurdtq] [--version] [--help] [--usage] [--run] [--dump] + [--time] [--noinit] [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 + +@defopt -t +@defoptx --time +This option must be used in conjuction with @code{-r}, and tells +@code{mixvm} to print virtual time statistics for the program's +execution. +@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. + +The first time @code{mixvm} is invoked, a directory named @file{.mdk} is +created in your home directory. It contains the @code{mixvm} +configuration file, the command history file and (by default) the block +devices files (@pxref{Devices}). Before showing you the command prompt, +@code{mixvm} looks in the @file{~/.mdk} directory for a file named +@code{mixguile.scm}; if it exists, it is read and evaluated by the +embedded Guile interpreter (@pxref{Defining new functions}). You can use +the @code{-q} command line option to skip this file loading: + +@defopt -q +@defoptx --noinit +Do not load the Guile initialisation file @code{~/.mdk/mixguile.scm} at +startup. +@end defopt + +@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 be greeted by a shell +prompt@footnote{The default command prompt, @samp{MIX > }, can be +changed using the @code{prompt} command (@pxref{Configuration commands})} + +@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)@footnote{The readline functionality will be available if you have +compiled @sc{mdk} with readline support, i.e., if GNU readline is +installed in your system. This is ofte the case in GNU/Linux and BSD +systems}. In a nutshell, readline provides command completion using the +@kbd{TAB} key and command history using the cursor keys. A history file +containing the last commands typed in previous sessions is stored in the +@sc{mdk} configuration directory (@file{~/.mdk}). + +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] +Prints a short description of the given @var{command} and its usage. If +@var{command} is omitted, @code{help} prints the short description for +all available commands. +@end deffn + +@menu +* File commands:: Loading and executing programs. +* Debug commands:: Debugging programs. +* State commands:: Inspecting the virtual machine state. +* Configuration commands:: Changing and storing mixvm settings. +* Scheme commands:: +@end menu + +@node File commands, Debug commands, Commands, Commands +@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 (as a matter of fact, a @code{load} command +preserving the currently set breakpoints is issued before resuming +execution). +@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}. If invoked without argument, the source file for the +currently loaded MIX file is edited. The command used to edit source +files can also be configured using the @code{sedit} command +(@pxref{Configuration commands}). +@end deffn + +@deffn {file command} compile file[.mixal] +The source file @var{file.mixal} is compiled (with debug information +enabled) using @code{mixasm}. If invoked without argument, the source +file for the currently loaded MIX file is recompiled. The compilation +command can be set using the @code{sasm} command (@pxref{Configuration +commands}). +@end deffn + +@deffn {file command} pprog +@deffnx {file command} psrc +Print the path of the currently loaded MIX program and its source file: + +@example +MIX > load ../samples/primes +Program loaded. Start address: 3000 +MIX > pprog +../samples/primes.mix +MIX > psrc +/home/jao/projects/mdk/gnu/samples/primes.mixal +MIx> +@end example +@end deffn + +Finally, you can use the @code{quit} command to exit @code{mixvm}: + +@deffn {file command} quit +Exit @code{mixvm}, saving the current configuration parameters in +@file{~/.mdk/mixvm.config}. +@end deffn + + +@node Debug commands, State commands, File commands, Commands +@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. If @code{next} 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 (as a matter of fact, a @code{load} command +preserving the currently set breakpoints is issued before resuming +execution). +@end deffn + +@deffn {debug command} sbp line_number +@deffnx {debug command} cbp line_no +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). + +The command @code{cbp} clears a (previously set) breakpoint at the given +source file line. +@end deffn + +@deffn {debug command} spba address +@deffnx {debug command} cbpa 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}. +The command @code{cbpa} clears a (previously set) breakpoint at the +given memory address. +@end deffn + +@deffn {debug command} sbpr A | X | J | Ii +@deffnx {debug command} cbpr A | X | J | Ii +Sets a conditional breakpoint on the specified register change. For +instance, + +@example +sbpr I1 +@end example + +@noindent +will cause an interruption during program execution whenever the +contents or register @code{I1} changes. A previously set breakpoint is +cleared using the @code{cbpr} command. +@end deffn + +@deffn {debug command} sbpm address +@deffnx {debug command} cbpm address +Sets a conditional breakpoint on the specified memory cell change. The +argument must be a valid MIX memory address, i.e., it must belong into +the range @w{[0-3999]}. For instance, + +@example +sbpm 1000 +@end example + +@noindent +will cause an interruption during program execution whenever the +contents or of the memory cell number 1000 changes. A previously set +breakpoint is cleared using the @code{cbpm} command. +@end deffn + +@deffn {debug command} sbpo +@deffnx {debug command} cbpo +Sets/clears a conditional breakpoint on overflow toggle change. +@end deffn + +@deffn {debug command} sbpc +@deffnx {debug command} cbpc +Sets/clears a conditional breakpoint on comparison flag change. +@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. 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} strace [on|off] +@code{strace on} 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 disabled with @code{strace off} +command. A typical tracing session could be like this: + +@example +MIX > strace 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 > strace 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. The +tracing behaviour is stored as a configuration parameter in @file{~/.mdk}. +@end deffn + +@deffn {debug command} pline [LINE_NUMBER] +Prints the requested source line (or the current one if +@var{line_number} is omitted: + +@example +MIX > load ../samples/hello +Program loaded. Start address: 3000 +MIX > pline +Line 5: START OUT MSG(TERM) +MIX > pline 6 +Line 6: HLT +MIX > +@end example +@end deffn + +@deffn {debug command} pbt [INS_NUMBER] +This command prints a backtrace of executed instructions. Its optional +argument @var{ins_number} is the number of instructions to print. If it +is omitted or equals zero, all executed instructions are printed. For +instance, if you compile and load the following program (@file{bt.mixal}): + +@example + ORIG 0 +BEG JMP *+1 + JMP *+1 +FOO JMP BAR +BAR HLT + END BEG +@end example + +@noindent +you could get the following traces: + +@example +MIX > load bt +Program loaded. Start address: 0 +MIX > next +MIX > pbt +#0 BEG in bt.mixal:2 +MIX > next +MIX > pbt +#0 1 in bt.mixal:3 +#1 BEG in bt.mixal:2 +MIX > run +Running ... +... done +MIX > pbt 3 +#0 BAR in bt.mixal:5 +#1 FOO in bt.mixal:4 +#2 1 in bt.mixal:3 +MIX > pbt +#0 BAR in bt.mixal:5 +#1 FOO in bt.mixal:4 +#2 1 in bt.mixal:3 +#3 BEG in bt.mixal:2 +MIX > +@end example + +Note that the executed instruction trace gives you the label of the +executed line or, if it has no label, its address. +@end deffn + +As you have probably observed, @code{mixvm} prints timing statistics +when running programs. This behaviour can be controlled using the +@code{stime} command (@pxref{Configuration commands}). + +@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, Configuration commands, Debug commands, Commands +@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} pstat +This commands prints the current virtual machine state, which can be one +of the following: +@itemize @minus +@item +No program loaded +@item +Program successfully loaded +@item +Execution stopped (@code{next} executed) +@item +Execution stopped: breakpoint encountered +@item +Execution stopped: conditional breakpoint encountered +@item +Program successfully terminated +@end itemize +@end deffn + +@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} sreg A | X | J | I[1-6] value +@deffnx {state command} preg [A | X | J | I[1-6]] +@deffnx {state command} pall +@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, @code{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 + +@node Configuration commands, Scheme commands, State commands, Commands +@subsection Configuration commands + +This section describes commands that allow you to configure the virtual +machine behaviour. This configuration is stored in the @sc{mdk} +directory @file{~/.mdk}. + +As you can see in their description, some commands print, as a side +effect, informational messages to the standard output (e.g. @code{load} +prints a message telling you the loaded program's start address): these +messages can be enabled/disabled using @code{slog}: + +@deffn {config command} slog on|off +Turns on/off the logging of informational messages. Note that error +messages are always displayed, as well as state messages required using +commands prefixed with @code{p} (@code{preg}, @code{pmem} and the like). +@end deffn + +@deffn {config command} stime on|off +@deffnx {config command} ptime +The @code{stime} command (un)sets the printing of timing statistics, and +@code{ptime} prints their current value: + +@example +MIX > ptime +Elapsed time: 10 /Total program time: 11 (Total uptime: 11) +MIX > +@end example +@end deffn + +@deffn {config command} sedit TEMPLATE +@deffnx {config command} pedit +@code{sedit} sets the command to be used to edit MIXAL source files with +the @code{edit} command. @var{TEMPLATE} must contain the control +characters @code{%s} to mark the place where the source's file name will +be inserted. For instance, if you type + +@example +MIX > sedit emacsclient %s +MIX > +@end example + +issuing the @code{mixvm} command @w{@code{edit foo.mixal}} will invoke +the operating system command @w{@code{emacsclient foo.mixal}}. + +@code{pedit} prints the current value of the edit command template. + +@end deffn + +@deffn {config command} sasm TEMPLATE +@deffnx {config command} pasm +@code{sasm} sets the command to be used to compile MIXAL source files with +the @code{compile} command. @var{template} must contain the control +characters @code{%s} to mark the place where the source's file name will +be inserted. For instance, if you type + +@example +MIX > sasm mixasm -l %s +MIX > +@end example + +issuing the @code{mixvm} command @w{@code{compile foo.mixal}} will invoke +the operating system command @w{@code{mixasm -l foo.mixal}}. + +@code{pasm} prints the current value of the compile command template. + +@end deffn + +@deffn {config command} sddir DIRNAME +@deffnx {config command} pddir +MIX devices (@pxref{Devices}) are implemented as regular files stored, +by default, inside @file{~/.mdk}. The @code{sddir} command lets you +specify an alternative location for storing these device files, while +@code{pddir} prints the current device directory. +@end deffn + +Finally, you can change the default command prompt, @samp{MIX > }, +using the @code{prompt} command: + +@deffn {config command} prompt PROMPT +Changes the command prompt to @var{prompt}. If you want to include +white space(s) at the end of the new prompt, bracket @var{prompt} using +double quotes (e.g., @code{prompt ">> "}). +@end deffn + +@node Scheme commands, , Configuration commands, Commands +@subsection Scheme commands + +If you have compiled @sc{mdk} with @code{libguile} support +(@pxref{Special configure flags}), @code{mixvm} will start and +initialise an embedded Guile Scheme interpret when it is invoked. That +means that you have at your disposal, at @code{mixvm}'s command prompt, +all the Scheme primitives described in @ref{Using mixguile} and +@ref{mixguile}, as well as any other function or hook that you have +defined in the initialisation file @file{~/.mdk/mixguile.scm}. To +evaluate a Scheme function, simply type it at the @code{mixvm} command +prompt (see @ref{Using Scheme in mixvm and gmixvm} for a +sample). Compared to the @code{mixguile} program, this has only one +limitation: the expressions used in @code{mixvm} cannot span more than +one line. You can get over this inconvenience writing your multiline +Scheme expressions in a file and loading it using the @code{scmf} +command: + +@deffn {scheme command} scmf FILE_NAME +Loads the given Scheme file and evaluates it using the embedded Guile +interpreter. +@end deffn + + +@node Devices, , Commands, mixvm +@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 input/output. When you request an output operation on any other +(output) device, a file named according to the following table will be +created, 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). The device files are stored, by default, in the +directory @file{~/.mdk}; this location can be changed using the +@code{mixvm} command @code{devdir} (@pxref{Configuration commands}). + +@multitable {the device name} { xx-xx } {filename[x-x].dev} {bin i/o/char } +@item @emph{Device} @tab @emph{No.} @tab @emph{filename} @tab @emph{type and block size} +@item Tape @tab 0-7 @tab @file{tape[0-7].dev} @tab bin i/o - 100 words +@item Disks @tab 8-15 @tab @file{disk[0-7].dev} @tab bin i/o - 100 words +@item Card reader @tab 16 @tab @file{cardrd.dev} @tab char in - 16 words +@item Card writer @tab 17 @tab @file{cardwr.dev} @tab char out - 16 words +@item Line printer @tab 18 @tab @file{printer.dev} @tab char out - 24 words +@item Terminal @tab 19 @tab @code{stdin/stdout} @tab char i/o - 14 words +@item Paper tape @tab 20 @tab @file{paper.dev} @tab char in - 14 words +@end multitable + +Devices of type @i{char} are stored as ASCII files, using one line per +block. For instance, since the card reader has blocks of size 16, that +is, 80 characters, it will be emulated by an ASCII file consisting of +lines with length 80. If the reader finds a line with less than the +required number of characters, it pads the memory with zeroes (MIX +character 'space') to complete the block size. + +Note that the virtual machine automatically converts between the MIX and +ASCII character encodings, so that you can manipulate char device files +with any ASCII editor. In addition, the reader is not case-sensitive, +i.e., it automatically converts lowercase letters to their uppercase +counterparts (since the MIX character set does not include the former). + +The typewriter (device no. 19) lets you use the standard input and +output in your MIXAL programs. For instance, here is a simple 'echo' +program: + +@example +* simple echo program +TERM EQU 19 the typewriter device +BUF EQU 500 input buffer + ORIG 1000 +START IN BUF(TERM) read a block (70 chars) + OUT BUF(TERM) write the read chars + HLT + END START +@end example + +@noindent Input lines longer than 70 characters (14 words) are trimmed. +On the other hand, if you type less than a block of characters, +whitespace (MIX character zero) is used as padding. + diff --git a/doc/mdk_tut.texi b/doc/mdk_tut.texi new file mode 100644 index 0000000..0fabe89 --- /dev/null +++ b/doc/mdk_tut.texi @@ -0,0 +1,1319 @@ +@c -*-texinfo-*- +@c This is part of the GNU MDK Reference Manual. +@c Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 +@c Free Software Foundation, Inc. +@c See the file mdk.texi for copying conditions. + +@c $Id: mdk_tut.texi,v 1.14 2005/09/20 00:26:00 jao Exp $ + +@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 are 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 ~ @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 [ @tab 21 @tab # @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. The characters @code{~}, @code{[} and +@code{#} 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 + +Note that, when computing @samp{V} using a word and an fspec, we apply +a left padding to the bytes selected by @samp{MOD} to obtain a +complete word as the result. + +In the following subsections, we will +assign 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 contents of cell no. M, with opposite sign. +OPCODE = 16, MOD = fspec. @code{rA <- -V}. +@item LDXN +Put in rX the contents of cell no. M, with opposite sign. +OPCODE = 23, MOD = fspec. @code{rX <- -V}. +@item LDiN +Put in rIi the contents of cell no. M, with opposite sign. +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 + 3 + | | --- 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 + +@example +V = [M](3:3) = (- 01 02 03 04 05)(3:3) + = + 00 00 00 00 03 +@end example +@noindent +(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 other 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. Consequently, @samp{M} can have any valid word value (i.e., it's +not limited to the 0-3999 range of a memory address). + +@ftable @code +@item ENTA +Enter @samp{M} in [rA]. OPCODE = 48, MOD = 2. @code{rA <- M}. +@item ENTX +Enter @samp{M} in [rX]. OPCODE = 55, MOD = 2. @code{rX <- M}. +@item ENTi +Enter @samp{M} in [rIi]. OPCODE = 48 + i, MOD = 2. @code{rIi <- M}. +@item ENNA +Enter @samp{-M} in [rA]. OPCODE = 48, MOD = 3. @code{rA <- -M}. +@item ENNX +Enter @samp{-M} in [rX]. OPCODE = 55, MOD = 3. @code{rX <- -M}. +@item ENNi +Enter @samp{-M} in [rIi]. OPCODE = 48 + i, MOD = 3. @code{rIi <- -M}. +@item INCA +Increase [rA] by @samp{M}. OPCODE = 48, MOD = 0. @code{rA <- rA + M}. +@item INCX +Increase [rX] by @samp{M}. OPCODE = 55, MOD = 0. @code{rX <- rX + M}. +@item INCi +Increase [rIi] by @samp{M}. OPCODE = 48 + i, MOD = 0. @code{rIi <- rIi + M}. +@item DECA +Decrease [rA] by @samp{M}. OPCODE = 48, MOD = 1. @code{rA <- rA - M}. +@item DECX +Decrease [rX] by @samp{M}. OPCODE = 55, MOD = 1. @code{rX <- rX - M}. +@item DECi +Decrease [rIi] by @samp{M}. OPCODE = 48 + i, MaOD = 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, there 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 content 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 content 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 content 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 +0-9). Thus, if the contents of @samp{rA} and @samp{rX} are, 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). + +If any byte in @samp{rA} or @samp{rB} does not belong to the range +30-39, it is interpreted by @samp{NUM} as the digit obtained by taking +its value modulo 10. E.g. values 0, 10, 20, 30, 40, 50, 60 all represent the +digit 0; 2, 12, 22, etc. represent the digit 2, and so on. For +instance, the number 0012315904 mentioned above could also be +represented as + +@example +[rA] = + 10 40 31 52 23 +[rX] = + 11 35 49 20 54 +@end example + +@samp{CHAR} performs the inverse operation, using only the values 30 +to 39 for representing digits 0-9. + +@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 (see example below) +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 SLA 6 @tab [rA] = - 00 00 00 00 00 +@item SRA 1 @tab [rA] = - 00 01 02 03 04 +@end multitable +@noindent +Note that the sign is unaffected by shift operations. On the other +hand, @samp{SLC}, @samp{SRC}, @samp{SLAX} and @samp{SRAX} treat +@samp{rA} and @samp{rX} as a single 10-bytes register (ignoring again +the signs). For instance, if we begin with @samp{[rA]} = @w{+ 01 02 03 +04 05} and @samp{[rX]} = @w{- 06 07 08 09 10}, we would have: + +@multitable {SLC 00} {[rA] = - 00 00 00 00 00} {[rA] = - 00 00 00 00 00} +@item SLC 3 @tab [rA] = + 04 05 06 07 08 @tab [rX] = - 09 10 01 02 03 +@item SLAX 3 @tab [rA] = + 04 05 06 07 08 @tab [rX] = - 09 10 00 00 00 +@item SRC 4 @tab [rA] = + 07 08 09 10 01 @tab [rX] = - 02 03 04 05 06 +@item SRAX 4 @tab [rA] = + 00 00 00 00 01 @tab [rX] = - 02 03 04 05 06 +@end multitable + +@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 words. +@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 (optionally) 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+2F +@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 +is an expression evaluating to the address subfield of the instruction, +@item INDEX +is an expression evaluating to the index subfield of the instruction, which +defaults to 0 (i.e., no use of indexing) and can only be used when +@code{ADDRESS} is present, +@item MOD +is an 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; 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 (optionally 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 @footnote{In the original +MIXAL definition, the @code{ALF} argument is not quoted. You can write +the operand (as the @code{ADDRESS} field) without quotes, but, in this +case, you must follow the alignment rules of the original MIXAL +definition (namely, the @code{ADDRESS} must start at column 17).}: + +@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{OPERAND} 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. Operator precedence 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 6 (4 plus 2) 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) +@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 standalone (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 an 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 from left to right as follows: + +@itemize +@item +Start with an accumulated result @samp{w} equal to 0. +@item +Take the first expression of the comma-separated list and evaluate +it. For instance, if the w-expression is @samp{S1+2(2:4),2000(S2)}, we +evaluate first @samp{S1+2}; let's suppose that @samp{S1} equals +265230: then @samp{S1+2 = 265232 = + 00 01 00 48 16}. +@item +Evaluate the expression within parenthesis, reducing it to an f-spec +of the form @samp{L:R}. In our previous example, the expression +between parenthesis already has the desired form: 2:4. +@item +Substitute the bytes of the accumulated result @samp{w} designated by +the f-spec using those of the previous expression value. In our sample, +@samp{w = + 00 00 00 00 00}, and we must substitute bytes 2, 3 and 4 of +@samp{w} using values from 265232. We need 3 bytes, and we take the +least significant ones: 00, 48, and 16, and insert them in positions +2, 3 and 4 of @samp{w}, obtaining @samp{w = + 00 00 48 16 00}. +@item +Repeat this operation with the remaining terms, acting on the new +value of @samp{w}. In our example, if, say, @samp{S2 = 1:1}, we must +substitute the first byte of @samp{w} using one byte (the least +significant) from 2000, that is, 16 (since 2000 = + 00 00 00 31 16) +and, therefore, we obtain @samp{w = + 16 00 48 16 00}; summing up, we +have obtained @samp{265232(1:4),2000(1:1) = + 16 00 48 16 00 = +268633088}. +@end itemize + +As a second example, 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 it is 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{wexp} is a w-expression (@pxref{W-expressions}). For instance, the +code + +@example +L EQU 5 + LDA =20-L= +@end example + +causes the assembler to add after the program's end an instruction +with contents 15 (@samp{20-L}), and to assemble the above code as the +instruction @w{@code{ LDA a}}, where @code{a} stands for the address +in which the value 15 is stored. In other words, the compiled code is +equivalent to the following: + +@example +L EQU 5 + LDA a +@dots{} +a CON 20-L + END start +@end example + diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 0000000..db3f35f --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,17 @@ +## 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 = getopt_long.c getopt.h + +noinst_LIBRARIES = libreplace.a +libreplace_a_SOURCES = +libreplace_a_LIBADD = @LIBOBJS@ \ No newline at end of file diff --git a/lib/getopt.h b/lib/getopt.h new file mode 100644 index 0000000..4ac33b7 --- /dev/null +++ b/lib/getopt.h @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/lib/getopt_long.c b/lib/getopt_long.c new file mode 100644 index 0000000..8abb3ac --- /dev/null +++ b/lib/getopt_long.c @@ -0,0 +1,1086 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 + Free Software Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#ifdef VMS +# include +# if HAVE_STRING_H - 0 +# include +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include +# define _(msgid) gettext (msgid) +# else +# define _(msgid) (msgid) +# endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +# include +# define my_index strchr +#else + +# if HAVE_STRING_H +# include +# else +# if HAVE_STRINGS_H +# include +# endif +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +# if (!defined __STDC__ || !__STDC__) && !defined strlen +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +# endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +# ifdef text_set_element +text_set_element (__libc_subinit, store_args_and_env); +# endif /* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined __STDC__ && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined __STDC__ && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + + + +#endif /* TEST */ diff --git a/mdk.spec b/mdk.spec new file mode 100644 index 0000000..356ddb5 --- /dev/null +++ b/mdk.spec @@ -0,0 +1,142 @@ +%define name mdk +%define docname mdk-doc +%define version 0.4.2 +%define release 1 +%define serial 2 +#%define prefix /opt/mdk-0.3.1/usr +%define prefix /usr +#%define infodirdir %{prefix}/etc/ +%define infodirdir /etc +Summary: MIX Development Kit +Name: %{name} +Version: %{version} +Release: %{release} +Serial: %{serial} +Copyright: GPL +Group: Development/Languages +Url: http://www.gnu.org/software/mdk/mdk.html +Vendor: Jose A. Ortega Ruiz +Source0: http://download.sourcegorge.net/mdk/%{name}-%{version}.tar.gz +Source1: http://download.sourcegorge.net/mdk/%{docname}-%{version}.tar.gz +#Patch0: patch-mdk-0.3 +Packager: Agustin Navarro +BuildRoot: /var/tmp/%{name}-%{version}-root +#DocDir: %{prefix}/share/doc/mdk-0.3.1 + + +%description +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 case you are an Emacs guy, +you can try doc/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). + + +%package gtk +Summary: MIX Development Kit GTK GUI Interface to mixvm +Group: Development/Languages + +%description gtk +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. + +A GTK+ GUI to mixvm, called gmixvm, is provided + +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). + + +%package doc +Summary: MIX Development Kit HTML Documentation +Group: Development/Languages + +%description doc +MDK stands for MIX Development Kit, and provides tools for developing +and executing, in a MIX virtual machine, MIXAL programs. + +This pakage includes the HTML Documentation + + +%prep + +%setup -q +%setup -D -T -b 1 + +#%patch0 -p1 + +CFLAGS=$RPM_OPT_FLAGS \ + ./configure --prefix=%{prefix} --infodir='${prefix}/share/info' + +%build +make +#make html + +%install +[ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; +make -e prefix=$RPM_BUILD_ROOT%{prefix} install + +%clean +[ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT; + +%post +/sbin/install-info %{prefix}/share/info/mdk.info.gz %{infodirdir}/info-dir + +%files +%defattr(-,root,root) +%doc AUTHORS ChangeLog COPYING README NEWS TODO THANKS INSTALL +%doc samples +%doc misc/mixvm.el +%{prefix}/bin/mixasm +%{prefix}/bin/mixvm +%{prefix}/share/info/* + +%files gtk +%defattr(-,root,root) +%{prefix}/share/mdk +%{prefix}/bin/gmixvm + +%files doc +%defattr(-,root,root) +%doc ../%{docname}-%{version}/img ../%{docname}-%{version}/manual + + +%changelog +* Sun Aug 19 2001 Agustin Navarro +- Upgrade to mdk-0.4 + +* Sun Jul 22 2001 Agustin Navarro +- Upgrade to mdk-0.4 + +* Thu Jun 21 2001 Agustin Navarro +- Upgrade to mdk-0.3.5 + +* Tue Jun 12 2001 Agustin Navarro +- Upgrade to mdk-0.3.4 + +* Sat Jun 09 2001 Agustin Navarro +- Upgrade to mdk-0.3.3 + +* Thu May 16 2001 Agustin Navarro +- Upgrade to 0.3.2 + +* Fri Mar 30 2001 Agustin Navarro +- Initial Rpm Release + + diff --git a/misc/Makefile.am b/misc/Makefile.am new file mode 100644 index 0000000..f703ba0 --- /dev/null +++ b/misc/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2001, 2003 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 mixal-mode.el + +pkgdata_DATA = mixvm.el mixal-mode.el + diff --git a/misc/mixal-mode.el b/misc/mixal-mode.el new file mode 100644 index 0000000..638947a --- /dev/null +++ b/misc/mixal-mode.el @@ -0,0 +1,1321 @@ +;;; mixal-mode.el --- Major mode for the mix asm language. + +;; Copyright (C) 2003, 2005 Free Software Foundation + +;; 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., 51 Franklin Street, Fifth Floor, Boston, +;; MA 02110-1301 USA + +;; Author: Pieter E.J. Pareit +;; Maintainer: Pieter E.J. Pareit +;; Created: 09 Nov 2002 +;; Version: 0.1 +;; Keywords: Knuth mix mixal asm mixvm "The Art Of Computer Programming" + +;;; Commentary: +;; Major mode for the mix asm language. +;; The mix asm language is described in "The Art Of Computer Programming". +;; +;; For optimal use, also use GNU MDK. Compiling needs mixasm, running +;; and debugging needs mixvm and mixvm.el from GNU MDK. You can get +;; GNU MDK from `https://savannah.gnu.org/projects/mdk/' and +;; `ftp://ftp.gnu.org/pub/gnu/mdk'. +;; +;; To use this mode, place the following in your .emacs file: +;; `(load-file "/PATH-TO-FILE/mixal-mode.el")'. +;; When you load a file with the extension .mixal the mode will be started +;; automatic. If you want to start the mode manual, use `M-x mixal-mode'. +;; Font locking will work, the behavior of tabs is the same as emacs +;; default behavior. You can compile a source file with `C-c c' you can +;; run a compiled file with `C-c r' or run it in debug mode with `C-c d'. +;; You can get more information about a particular operation code by using +;; mixal-describe-operation-code or `C-h o'. +;; +;; Have fun. + +;;; History: +;; Version 0.2: +;; 06/04/05: mixasm no longer needs -g option +;; fontlocking of comments works in all? cases now +;; added some more mixal-operation-codes +;; Version 0.1: +;; Version 0.1.1: +;; 22/11/02: bugfix in fontlocking, needed to add a '-' to the regex. +;; 19/11/02: completed implementing mixal-describe-operation-code. +;; 13/11/02: implemented compile, mixal-run and mixal-debug. +;; 10/11/02: implemented font-locking and syntax table. +;; 09/11/02: started mixal-mode. + +;;; Code: + +;;; Key map +(defvar mixal-mode-map + (let ((map (make-sparse-keymap))) + (define-key map "\C-cc" 'compile) + (define-key map "\C-cr" 'mixal-run) + (define-key map "\C-cd" 'mixal-debug) + (define-key map "\C-ho" 'mixal-describe-operation-code) + map) + "Keymap for `mixal-mode'.") +; (makunbound 'mixal-mode-map) + +;;; Syntax table +(defvar mixal-mode-syntax-table + (let ((st (make-syntax-table))) + ; (modify-syntax-entry ?* "<" st) we need to do a bit more to make + ; (modify-syntax-entry ?\n ">" st) fontlocking for comments work + st) + "Syntax table for `dot-mode'.") + +(defvar mixal-font-lock-label-face 'font-lock-variable-name-face + "Face name to use for label names. +Default value is that of `font-lock-variable-name-face', but you can modify +its value.") + +(defvar mixal-font-lock-operation-code-face 'font-lock-keyword-face + "Face name to use for operation code names. +Default value is that of `font-lock-keyword-face', but you can modify its +value.") + +(defvar mixal-font-lock-assembly-pseudoinstruction-face 'font-lock-builtin-face + "Face name to use for assembly pseudoinstruction names. +Default value is that of `font-lock-builtin-face', but you can modify its +value.") + +(defvar mixal-operation-codes + '("NOP" "ADD" "FADD" "SUB" "FSUB" "MUL" "FMUL" "DIV" "FDIV" "NUM" "CHAR" + "HLT" "SLA" "SRA" "SLAX" "SRAX" "SLC" "SRC" "MOVE" "LDA" "LD1" "LD2" "LD3" + "LD4" "LD5" "LD6" "LDX" "LDAN" "LD1N" "LD2N" "LD3N" "LD4N" "LD5N" "LD6N" + "LDXN" "STA" "ST1" "ST2" "ST3" "ST4" "ST5" "ST6" "STX" "STJ" "STZ" "JBUS" + "IOC" "IN" "OUT" "JRAD" "JMP" "JSJ" "JOV" "JNOV" + "JL" "JE" "JG" "JGE" "JNE" "JLE" + "JAN" "J1N" "J2N" "J3N" "J4N" "J5N" "J6N" "JXN" + "JAZ" "J1Z" "J2Z" "J3Z" "J4Z" "J5Z" "J6Z" "JXZ" + "JAP" "J1P" "J2P" "J3P" "J4P" "J5P" "J6P" "JXP" + "JANN" "J1NN" "J2NN" "J3NN" "J4NN" "J5NN" "J6NN" "JXNN" + "JANZ" "J1NZ" "J2NZ" "J3NZ" "J4NZ" "J5NZ" "J6NZ" "JXNZ" + "JANP" "J1NP" "J2NP" "J3NP" "J4NP" "J5NP" "J6NP" "JXNP" + "INCA" "DECA" "ENTA" "ENNA" "INC1" "DEC1" "ENT1" "ENN1" + "INC2" "DEC2" "ENT2" "ENN2" "INC3" "DEC3" "ENT3" "ENN3" "INC4" "DEC4" + "ENT4" "ENN4" "INC5" "DEC5" "ENT5" "ENN5" "INC6" "DEC6" "ENT6" "ENN6" + "INCX" "DECX" "ENTX" "ENNX" "CMPA" "FCMP" "CMP1" "CMP2" "CMP3" "CMP4" + "CMP5" "CMP6" "CMPX") + "List of possible operation codes as strings.") +; (makunbound 'mixal-operation-codes) + +(defvar mixal-assembly-pseudoinstructions + '("ORIG" "EQU" "CON" "ALF" "END") + "List of possible assembly pseudoinstructions") + +;;; Font-locking: +(defvar mixal-font-lock-keywords + `(("^\\([A-Z0-9a-z]+\\).*$" + (1 mixal-font-lock-label-face)) + (,(regexp-opt mixal-operation-codes 'words) + . mixal-font-lock-operation-code-face) + (,(regexp-opt + mixal-assembly-pseudoinstructions 'words) + . mixal-font-lock-assembly-pseudoinstruction-face) + ("^[A-Z0-9a-z]*[ \t]+[A-ZO-9a-z]+[ \t]+\\(=.*=\\).*$" + (1 font-lock-constant-face)) + ("^[A-Z0-9a-z]*[ \t]+[A-Z0-9a-z]+[ \t]+[A-Z0-9a-z,():+-\\*=\" ]*[\t]+\\(.*\\)$" + (1 font-lock-comment-face)) + ("^\\*.*$" . font-lock-comment-face)) + "Keyword highlighting specification for `mixal-mode'.") +; (makunbound 'mixal-font-lock-keywords) + +;;;; Compilation +;; Output from mixasm is compatible with default behavior of emacs, +;; I just added a key (C-cc) and modified the make-command. + +;;;; Indentation +;; Tabs works well by default. + +;;;; Describe +(defvar mixal-operation-codes-alist '() + "Alist that contains all the possible operation codes for mix. +Each elt has the form (OP-CODE GROUP FULL-NAME C-BYTE F-BYTE DESCRIPTION EXECUTION-TIME) +Where OP-CODE is the text of the opcode as an symbol, FULL NAME is the human readable name +as a string, C-BYTE is the operation code telling what operation is to be performed, F-BYTE holds +an modification of the operation code which can be a symbol or a number, DESCRIPTION contains +an string with a description about the operation code and EXECUTION-TIME holds info +about the time it takes, number or string") +; (makunbound 'mixal-operation-codes-alist) + +(defun mixal-add-operation-code (op-code group full-name C-byte F-byte description execution-time) + "Add an operation code to the list that contains information about possible op code's." + (setq mixal-operation-codes-alist (cons (list op-code group full-name C-byte F-byte + description execution-time) + mixal-operation-codes-alist ))) + +;; now add each operation code + +(mixal-add-operation-code + 'LDA 'loading "load A" 8 'field + "Put in rA the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word." + 2) + +(mixal-add-operation-code + 'LDX 'loading "load X" 15 'field + "Put in rX the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word." + 2) + +(mixal-add-operation-code + 'LD1 'loading "load I1" (+ 8 1) 'field + "Put in rI1 the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word. Index registers only have 2 bytes and a sign, Trying +to set anything more that that will result in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD2 'loading "load I2" (+ 8 2) 'field + "Put in rI2 the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word. Index registers only have 2 bytes and a sign, Trying +to set anything more that that will result in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD3 'loading "load I3" (+ 8 3) 'field + "Put in rI3 the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word. Index registers only have 2 bytes and a sign, Trying +to set anything more that that will result in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD4 'loading "load I4" (+ 8 4) 'field + "Put in rI4 the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word. Index registers only have 2 bytes and a sign, Trying +to set anything more that that will result in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD5 'loading "load I5" (+ 8 5) 'field + "Put in rI5 the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word. Index registers only have 2 bytes and a sign, Trying +to set anything more that that will result in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD6 'loading "load I6" (+ 8 6) 'field + "Put in rI6 the contents of cell no. M. +Uses a + when there is no sign in subfield. Subfield is left padded with +zeros to make a word. Index registers only have 2 bytes and a sign, Trying +to set anything more that that will result in undefined behavior." + 2) + +(mixal-add-operation-code + 'LDAN 'loading "load A negative" 16 'field + "Put in rA the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word." + 2) + +(mixal-add-operation-code + 'LDXN 'loading "load X negative" 23 'field + "Put in rX the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word." + 2) + +(mixal-add-operation-code + 'LD1N 'loading "load I1 negative" (+ 16 1) 'field + "Put in rI1 the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word. Index registers only +have 2 bytes and a sign, Trying to set anything more that that will result +in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD2N 'loading "load I2 negative" (+ 16 2) 'field + "Put in rI2 the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word. Index registers only +have 2 bytes and a sign, Trying to set anything more that that will result +in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD3N 'loading "load I3 negative" (+ 16 3) 'field + "Put in rI3 the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word. Index registers only +have 2 bytes and a sign, Trying to set anything more that that will result +in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD4N 'loading "load I4 negative" (+ 16 4) 'field + "Put in rI4 the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word. Index registers only +have 2 bytes and a sign, Trying to set anything more that that will result +in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD5N 'loading "load I5 negative" (+ 16 5) 'field + "Put in rI5 the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word. Index registers only +have 2 bytes and a sign, Trying to set anything more that that will result +in undefined behavior." + 2) + +(mixal-add-operation-code + 'LD6N 'loading "load I6 negative" (+ 16 6) 'field + "Put in rI6 the contents of cell no. M, with opposite sign. +Uses a + when there is no sign in subfield, otherwise use the opposite sign. +Subfield is left padded with zeros to make a word. Index registers only +have 2 bytes and a sign, Trying to set anything more that that will result +in undefined behavior." + 2) + +(mixal-add-operation-code + 'STA 'storing "store A" 24 'field + "Store in cell Nr. M the contents of rA. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield." + 2) + +(mixal-add-operation-code + 'STX 'storing "store X" 31 'field + "Store in cell Nr. M the contents of rX. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield." + 2) + +(mixal-add-operation-code + 'ST1 'storing "store I1" (+ 24 1) 'field + "Store in cell Nr. M the contents of rI1. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield. +Because index registers only have 2 bytes and a sign, the rest of the bytes +are assumed to be 0." + 2) + +(mixal-add-operation-code + 'ST2 'storing "store I2" (+ 24 2) 'field + "Store in cell Nr. M the contents of rI2. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield. +Because index registers only have 2 bytes and a sign, the rest of the bytes +are assumed to be 0." + 2) + +(mixal-add-operation-code + 'ST3 'storing "store I3" (+ 24 3) 'field + "Store in cell Nr. M the contents of rI3. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield. +Because index registers only have 2 bytes and a sign, the rest of the bytes +are assumed to be 0." + 2) + +(mixal-add-operation-code + 'ST4 'storing "store I4" (+ 24 4) 'field + "Store in cell Nr. M the contents of rI4. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield. +Because index registers only have 2 bytes and a sign, the rest of the bytes +are assumed to be 0." + 2) + +(mixal-add-operation-code + 'ST5 'storing "store I5" (+ 24 5) 'field + "Store in cell Nr. M the contents of rI5. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield. +Because index registers only have 2 bytes and a sign, the rest of the bytes +are assumed to be 0." + 2) + +(mixal-add-operation-code + 'ST6 'storing "store I6" (+ 24 6) 'field + "Store in cell Nr. M the contents of rI6. +The modification of the operation code 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. The +sign of the memory cell is not changed, unless it is part of the subfield. +Because index registers only have 2 bytes and a sign, the rest of the bytes +are assumed to be 0." + 2) + +(mixal-add-operation-code + 'STJ 'storing "store J" 32 'field + "Store in cell Nr. M the contents of rJ. +The modification of the operation code 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. The sign +of rJ is always +, sign of the memory cell is not changed, unless it is +part of the subfield. The default field for STJ is (0:2)." + 2) + +(mixal-add-operation-code + 'STZ 'storing "store zero" 33 'field + "Store in cell Nr. M '+ 0'. +The modification of the operation code represents the subfield of the +memory cell that is to be overwritten with zeros." + 2) + +(mixal-add-operation-code + 'ADD 'arithmetic "add" 1 'field + "Add to A the contents of cell Nr. M. +Subfield is padded with zero to make a word. +If the result is to large, the operation result modulo 1,073,741,823 (the +maximum value storable in a MIX word) is stored in `rA', and the overflow +toggle is set to TRUE." + 2) + +(mixal-add-operation-code + 'SUB 'arithmetic "subtract" 2 'field + "Subtract to A the contents of cell Nr. M. +Subfield is padded with zero to make a word. +If the result is to large, the operation result modulo 1,073,741,823 (the +maximum value storable in a MIX word) is stored in `rA', and the overflow +toggle is set to TRUE." + 2) + +(mixal-add-operation-code + 'MUL 'arithmetic "multiply" 3 'field + "Multiplies the contents of cell Nr. M with A, result is 10 bytes and stored in rA and rX. +The sign is + if the sign of rA and cell M where the same, otherwise, it is -" + 10) + +(mixal-add-operation-code + 'DIV 'arithmetic "divide" 4 'field + "Both rA and rX are taken together and divided by cell Nr. M, quotient is placed in rA, remainder in rX. +The sign is taken from rA, and after the divide the sign of rA is set to + when +both the sign of rA and M where the same. Divide by zero and overflow of rA result +in undefined behavior." + 12) + +(mixal-add-operation-code + 'ENTA 'address-transfer "enter A" 48 2 + "Literal value is stored in rA. +Indexed, stores value of index in rA." + 1) + +(mixal-add-operation-code + 'ENTX 'address-transfer "enter X" 55 2 + "Literal value is stored in rX. +Indexed, stores value of index in rX." + 1) + +(mixal-add-operation-code + 'ENT1 'address-transfer "Enter rI1" (+ 48 1) 2 + "Literal value is stored in rI1. +Indexed, stores value of index in rI1." + 1) + +(mixal-add-operation-code + 'ENT2 'address-transfer "Enter rI2" (+ 48 2) 2 + "Literal value is stored in rI2. +Indexed, stores value of index in rI2." + 1) + +(mixal-add-operation-code + 'ENT3 'address-transfer "Enter rI3" (+ 48 3) 2 + "Literal value is stored in rI3. +Indexed, stores value of index in rI3." + 1) + +(mixal-add-operation-code + 'ENT4 'address-transfer "Enter rI4" (+ 48 4) 2 + "Literal value is stored in rI4. +Indexed, stores value of index in rI4." + 1) + +(mixal-add-operation-code + 'ENT5 'address-transfer "Enter rI5" (+ 48 5) 2 + "Literal value is stored in rI5. +Indexed, stores value of index in rI5." + 1) + +(mixal-add-operation-code + 'ENT6 'address-transfer "Enter rI6" (+ 48 6) 2 + "Literal value is stored in rI6. +Indexed, stores value of index in rI6." + 1) + +(mixal-add-operation-code + 'ENNA 'address-transfer "enter negative A" 48 3 + "Literal value is stored in rA with opposite sign. +Indexed, stores value of index in rA with opposite sign." + 1) + +(mixal-add-operation-code + 'ENNX 'address-transfer "enter negative X" 55 3 + "Literal value is stored in rX with opposite sign. +Indexed, stores value of index in rX with opposite sign." + 1) + +(mixal-add-operation-code + 'ENN1 'address-transfer "Enter negative rI1" (+ 48 1) 3 + "Literal value is stored in rI1 with opposite sign. +Indexed, stores value of index in rI1 with opposite sign." + 1) + +(mixal-add-operation-code + 'ENN2 'address-transfer "Enter negative rI2" (+ 48 2) 3 + "Literal value is stored in rI2 with opposite sign. +Indexed, stores value of index in rI2 with opposite sign." + 1) + +(mixal-add-operation-code + 'ENN3 'address-transfer "Enter negative rI3" (+ 48 3) 3 + "Literal value is stored in rI3 with opposite sign. +Indexed, stores value of index in rI3 with opposite sign." + 1) + +(mixal-add-operation-code + 'ENN4 'address-transfer "Enter negative rI4" (+ 48 4) 3 + "Literal value is stored in rI4 with opposite sign. +Indexed, stores value of index in rI4 with opposite sign." + 1) + +(mixal-add-operation-code + 'ENN5 'address-transfer "Enter negative rI5" (+ 48 5) 3 + "Literal value is stored in rI5 with opposite sign. +Indexed, stores value of index in rI5 with opposite sign." + 1) + +(mixal-add-operation-code + 'ENN6 'address-transfer "Enter negative rI6" (+ 48 6) 3 + "Literal value is stored in rI6 with opposite sign. +Indexed, stores value of index in rI6 with opposite sign." + 1) + +(mixal-add-operation-code + 'INCA 'address-transfer "increase A" 48 0 + "Increase register A with the literal value of M. +On overflow the overflow toggle is set." + 1) + +(mixal-add-operation-code + 'INCX 'address-transfer "increase X" 55 0 + "Increase register X with the literal value of M. +On overflow the overflow toggle is set." + 1) + +(mixal-add-operation-code + 'INC1 'address-transfer "increase I1" (+ 48 1) 0 + "Increase register I1 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'INC2 'address-transfer "increase I2" (+ 48 2) 0 + "Increase register I2 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'INC3 'address-transfer "increase I3" (+ 48 3) 0 + "Increase register I3 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'INC4 'address-transfer "increase I4" (+ 48 4) 0 + "Increase register I4 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'INC5 'address-transfer "increase I5" (+ 48 5) 0 + "Increase register I5 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'INC6 'address-transfer "increase I6" (+ 48 6) 0 + "Increase register I6 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'DECA 'address-transfer "decrease A" 48 1 + "Decrease register A with the literal value of M. +On overflow the overflow toggle is set." + 1) + +(mixal-add-operation-code + 'DECX 'address-transfer "decrease X" 55 1 + "Decrease register X with the literal value of M. +On overflow the overflow toggle is set." + 1) + +(mixal-add-operation-code + 'DEC1 'address-transfer "decrease I1" (+ 48 1) 1 + "Decrease register I1 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'DEC2 'address-transfer "decrease I2" (+ 48 2) 1 + "Decrease register I2 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'DEC3 'address-transfer "decrease I3" (+ 48 3) 1 + "Decrease register I3 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'DEC4 'address-transfer "decrease I4" (+ 48 4) 1 + "Decrease register I4 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'DEC5 'address-transfer "decrease I5" (+ 48 5) 1 + "Decrease register I5 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'DEC6 'address-transfer "decrease I6" (+ 48 6) 1 + "Decrease register I6 with the literal value of M. +The result is undefined when the result does not fit in +2 bytes." + 1) + +(mixal-add-operation-code + 'CMPA 'comparison "compare A" 56 'field + "Compare contents of A with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome." + 2) + + +(mixal-add-operation-code + 'CMPX 'comparison "compare X" 63 'field + "Compare contents of rX with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome." + 2) + + +(mixal-add-operation-code + 'CMP1 'comparison "compare I1" (+ 56 1) 'field + "Compare contents of rI1 with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome. Bit 1,2 and 3 +have a value of 0." + 2) + + +(mixal-add-operation-code + 'CMP2 'comparison "compare I2" (+ 56 2) 'field + "Compare contents of rI2 with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome. Bit 1,2 and 3 +have a value of 0." + 2) + + +(mixal-add-operation-code + 'CMP3 'comparison "compare I3" (+ 56 3) 'field + "Compare contents of rI3 with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome. Bit 1,2 and 3 +have a value of 0." + 2) + + +(mixal-add-operation-code + 'CMP4 'comparison "compare I4" (+ 56 4) 'field + "Compare contents of rI4 with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome. Bit 1,2 and 3 +have a value of 0." + 2) + + +(mixal-add-operation-code + 'CMP5 'comparison "compare I5" (+ 56 5) 'field + "Compare contents of rI5 with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome. Bit 1,2 and 3 +have a value of 0." + 2) + + +(mixal-add-operation-code + 'CMP6 'comparison "compare I6" (+ 56 6) 'field + "Compare contents of rI6 with contents of M. +The field specifier works on both fields. The comparison indicator +is set to LESS, EQUAL or GREATER depending on the outcome. Bit 1,2 and 3 +have a value of 0." + 2) + +(mixal-add-operation-code + 'JMP 'jump "jump" 39 0 + "Unconditional jump. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'JSJ 'jump "jump, save J" 39 1 + "Unconditional jump, but rJ is not modified." + 1) + +(mixal-add-operation-code + 'JOV 'jump "jump on overflow" 39 2 + "Jump if OV is set (and turn it off). +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'JNOV 'jump "Jump on no overflow" 39 3 + "Jump if OV is not set (and turn it off). +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'JL 'jump "Jump on less" 39 4 + "Jump if '[CM] = L'. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JE 'jump "Jump on equal" 39 5 + "Jump if '[CM] = E'. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JG 'jump "Jump on greater" 39 6 + "Jump if '[CM] = G'. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JGE 'jump "Jump on not less" 39 7 + "Jump if '[CM]' does not equal 'L'. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JNE 'jump "Jump on not equal" 39 8 + "Jump if '[CM]' does not equal 'E'. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JLE 'jump "Jump on not greater" 39 9 + "Jump if '[CM]' does not equal 'G'. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'JAN 'jump "jump A negative" 40 0 + "Jump if the content of rA is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JAZ 'jump "jump A zero" 40 1 + "Jump if the content of rA is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JAP 'jump "jump A positive" 40 2 + "Jump if the content of rA is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JANN 'jump "jump A non-negative" 40 3 + "Jump if the content of rA is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JANZ 'jump "jump A non-zero" 40 4 + "Jump if the content of rA is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JANP 'jump "jump A non-positive" 40 5 + "Jump if the content of rA is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'JXN 'jump "jump X negative" 47 0 + "Jump if the content of rX is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JXZ 'jump "jump X zero" 47 1 + "Jump if the content of rX is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JXP 'jump "jump X positive" 47 2 + "Jump if the content of rX is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JXNN 'jump "jump X non-negative" 47 3 + "Jump if the content of rX is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JXNZ 'jump "jump X non-zero" 47 4 + "Jump if the content of rX is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'JXNP 'jump "jump X non-positive" 47 5 + "Jump if the content of rX is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'J1N 'jump "jump I1 negative" (+ 40 1) 0 + "Jump if the content of rI1 is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J1Z 'jump "jump I1 zero" (+ 40 1) 1 + "Jump if the content of rI1 is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J1P 'jump "jump I1 positive" (+ 40 1) 2 + "Jump if the content of rI1 is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J1NN 'jump "jump I1 non-negative" (+ 40 1) 3 + "Jump if the content of rI1 is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J1NZ 'jump "jump I1 non-zero" (+ 40 1) 4 + "Jump if the content of rI1 is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J1NP 'jump "jump I1 non-positive" (+ 40 1) 5 + "Jump if the content of rI1 is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'J2N 'jump "jump I2 negative" (+ 40 1) 0 + "Jump if the content of rI2 is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J2Z 'jump "jump I2 zero" (+ 40 1) 1 + "Jump if the content of rI2 is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J2P 'jump "jump I2 positive" (+ 40 1) 2 + "Jump if the content of rI2 is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J2NN 'jump "jump I2 non-negative" (+ 40 1) 3 + "Jump if the content of rI2 is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J2NZ 'jump "jump I2 non-zero" (+ 40 1) 4 + "Jump if the content of rI2 is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J2NP 'jump "jump I2 non-positive" (+ 40 1) 5 + "Jump if the content of rI2 is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J3N 'jump "jump I3 negative" (+ 40 1) 0 + "Jump if the content of rI3 is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J3Z 'jump "jump I3 zero" (+ 40 1) 1 + "Jump if the content of rI3 is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J3P 'jump "jump I3 positive" (+ 40 1) 2 + "Jump if the content of rI3 is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J3NN 'jump "jump I3 non-negative" (+ 40 1) 3 + "Jump if the content of rI3 is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J3NZ 'jump "jump I3 non-zero" (+ 40 1) 4 + "Jump if the content of rI3 is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J3NP 'jump "jump I3 non-positive" (+ 40 1) 5 + "Jump if the content of rI3 is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J4N 'jump "jump I4 negative" (+ 40 1) 0 + "Jump if the content of rI4 is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J4Z 'jump "jump I4 zero" (+ 40 1) 1 + "Jump if the content of rI4 is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J4P 'jump "jump I4 positive" (+ 40 1) 2 + "Jump if the content of rI4 is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J4NN 'jump "jump I4 non-negative" (+ 40 1) 3 + "Jump if the content of rI4 is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J4NZ 'jump "jump I4 non-zero" (+ 40 1) 4 + "Jump if the content of rI4 is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J4NP 'jump "jump I4 non-positive" (+ 40 1) 5 + "Jump if the content of rI4 is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J5N 'jump "jump I5 negative" (+ 40 1) 0 + "Jump if the content of rI5 is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J5Z 'jump "jump I5 zero" (+ 40 1) 1 + "Jump if the content of rI5 is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J5P 'jump "jump I5 positive" (+ 40 1) 2 + "Jump if the content of rI5 is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J5NN 'jump "jump I5 non-negative" (+ 40 1) 3 + "Jump if the content of rI5 is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J5NZ 'jump "jump I5 non-zero" (+ 40 1) 4 + "Jump if the content of rI5 is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J5NP 'jump "jump I5 non-positive" (+ 40 1) 5 + "Jump if the content of rI5 is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J6N 'jump "jump I6 negative" (+ 40 1) 0 + "Jump if the content of rI6 is negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J6Z 'jump "jump I6 zero" (+ 40 1) 1 + "Jump if the content of rI6 is zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J6P 'jump "jump I6 positive" (+ 40 1) 2 + "Jump if the content of rI6 is positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J6NN 'jump "jump I6 non-negative" (+ 40 1) 3 + "Jump if the content of rI6 is non-negative. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J6NZ 'jump "jump I6 non-zero" (+ 40 1) 4 + "Jump if the content of rI6 is non-zero. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + + +(mixal-add-operation-code + 'J6NP 'jump "jump I6 non-positive" (+ 40 1) 5 + "Jump if the content of rI6 is non-positive. +Register J is set to the value of the next instruction that would have +been executed when there was no jump." + 1) + +(mixal-add-operation-code + 'SLA 'miscellaneous "shift left A" 6 0 + "Shift to A, M bytes left. +Hero's will be added to the right." + 2) + + +(mixal-add-operation-code + 'SRA 'miscellaneous "shift right A" 6 1 + "Shift to A, M bytes right. +Zeros will be added to the left." + 2) + + +(mixal-add-operation-code + 'SLAX 'miscellaneous "shift left AX" 6 2 + "Shift AX, M bytes left. +Zeros will be added to the right." + 2) + + + +(mixal-add-operation-code + 'SRAX 'miscellaneous "shift right AX" 6 3 + "Shift AX, M bytes right. +Zeros will be added to the left." + 2) + + +(mixal-add-operation-code + 'SLC 'miscellaneous "shift left AX circularly" 6 4 + "Shift AX, M bytes left circularly. +The bytes that fall off to the left will be added to the right." + 2) + + +(mixal-add-operation-code + 'SRC 'miscellaneous "shift right AX circularly" 6 4 + "Shift AX, M bytes right circularly. +The bytes that fall off to the right will be added to the left." + 2) + +(mixal-add-operation-code + 'MOVE 'miscellaneous "move" 7 'number + "Move MOD words from M to the location stored in rI1." + '(+ 1 (* 2 number))) + +(mixal-add-operation-code + 'NOP 'miscellaneous "no operation" 0 'ignored + "No operation, M and F are not used by the machine." + 1) + +(mixal-add-operation-code + 'HLT 'miscellaneous "halt" 5 2 + "Halt. +Stop instruction fetching." + 1) + +(mixal-add-operation-code + 'IN 'input-output "input" 36 'unit + "Transfer a block of words from the specified unit to memory. +The transfer starts at address M." + 1) + +(mixal-add-operation-code + 'OUT 'input-output "output" 37 'unit + "Transfer a block of words from memory. +The transfer starts at address M to the specified unit." + 1) + +(mixal-add-operation-code + 'IOC 'input-output "input-output control" 35 'unit + "Perform a control operation. +The control operation is given by M on the specified unit." + 1) + +(mixal-add-operation-code + 'JRED 'input-output "jump ready" 38 'unit + "Jump to M if the specified unit is ready." + 1) + + +(mixal-add-operation-code + 'JBUS 'input-output "jump busy" 34 'unit + "Jump to M if the specified unit is busy." + 1) + +(mixal-add-operation-code + 'NUM 'conversion "convert to numeric" 5 0 + "Convert rAX to its numerical value and store it in rA. +the register rAX is assumed to contain a character representation of +a number." + 10) + +(mixal-add-operation-code + 'CHAR 'conversion "convert to characters" 5 1 + "Convert the number stored in rA to a character representation. +The converted character representation is stored in rAX." + 10) + +(defvar mixal-describe-operation-code-history nil + "History list for describe operation code.") + +(defun mixal-describe-operation-code (&optional op-code) + "Display the full documentation of OP-CODE." + (interactive) + ;; we like to provide completition and history, so do it ourself (interactive "?bla")? + (unless op-code + (let* ((completion-ignore-case t) + ;; we already have a list, but it is not in the right format + ;; transform it to a valid table so completition can use it + (table (mapcar '(lambda (elm) + (cons (symbol-name (car elm)) nil)) + mixal-operation-codes-alist)) + ;; prompt is different depending on we are close to a valid op-code + (have-default (member (current-word) mixal-operation-codes)) + (prompt (concat "Describe operation code " + (if have-default + (concat "(default " (current-word) "): ") + ": ")))) + ;; as the operation code to the user + (setq op-code (completing-read prompt table nil t nil + 'mixal-describe-operation-code-history + (current-word))))) + ;; get the info on the op-code and output it to the help buffer + (let ((op-code-help (assq (intern-soft op-code) mixal-operation-codes-alist))) + (when op-code-help + (with-output-to-temp-buffer (buffer-name (get-buffer-create "*Help*")) + (princ op-code) (princ " is an mix operation code\n\n") + (princ (nth 5 op-code-help)) (terpri) (terpri) + (princ " group: ") (princ (nth 1 op-code-help)) (terpri) + (princ " nice name: ") (princ (nth 2 op-code-help)) (terpri) + (princ " OPCODE / C: ") (princ (nth 3 op-code-help)) (terpri) + (princ " MOD / F: ") (princ (nth 4 op-code-help)) (terpri) + (princ " time: ") (princ (nth 6 op-code-help)) (terpri))))) + +;;;; Running +(defun mixal-run () + "Run's mixal file in current buffer, assumes that file has been compiled" + (interactive) + (mixvm (concat "mixvm -r -t -d " + (file-name-sans-extension (buffer-file-name))))) + +(defun mixal-debug () + "Starts mixvm for debugging, assumes that file has been compiled with debugging support" + (interactive) + (mixvm (concat "mixvm " + (file-name-sans-extension (buffer-file-name))))) + +;;;###autoload +(define-derived-mode mixal-mode fundamental-mode "mixal" + "Major mode for the mixal asm language. +\\{mixal-mode-map}" + (set (make-local-variable 'comment-start) "*") + (set (make-local-variable 'comment-start-skip) "*") + (set (make-local-variable 'font-lock-defaults) '(mixal-font-lock-keywords)) +; might add an indent function in the future +; (set (make-local-variable 'indent-line-function) 'mixal-indent-line) + (set (make-local-variable 'compile-command) (concat "mixasm " + buffer-file-name)) + ;; mixasm will do strange when there is no final newline, + ;; let emacs ensure that it is always there + (set (make-local-variable 'require-final-newline) t)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.mixal\\'" . mixal-mode)) + +(provide 'mixal-mode) +;;; mixal-mode.el ends here diff --git a/misc/mixvm.el b/misc/mixvm.el new file mode 100644 index 0000000..c437dfd --- /dev/null +++ b/misc/mixvm.el @@ -0,0 +1,158 @@ +;;; mixvm.el --- mdk's mixvm / Emacs gud interaction +;; Copyright (C) 2001 Free Software Foundation, Inc. + +;; Author: Philip Ellis King +;; Maintainer: Philip Ellis King +;; 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) + (when (boundp 'gud-make-debug-menu) + (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/Makefile.am b/mixgtk/Makefile.am new file mode 100644 index 0000000..60adf8d --- /dev/null +++ b/mixgtk/Makefile.am @@ -0,0 +1,47 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2001, 2004 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. + +# $Id: Makefile.am,v 1.19 2005/09/18 21:49:40 jao Exp $ + +EXTRA_DIST = mixgtk.glade + +if MAKE_GUILE +GUILED = -DMAKE_GUILE +else +GUILED = +endif + +if MAKE_GUI + +pkgdata_DATA = mixgtk.glade + +INCLUDES = -I$(includedir) -I$(top_srcdir) \ + -DGLADE_FILE=\""$(pkgdatadir)/mixgtk.glade"\"\ + -DLOCAL_GLADE_FILE=\""$(srcdir)/mixgtk.glade"\"\ + $(GUILED) +LDADD = $(top_builddir)/mixlib/libmix.a $(top_builddir)/lib/libreplace.a\ + $(top_builddir)/mixguile/libmixguile.a $(INTLLIBS) + +AM_LDFLAGS = -Wl,--export-dynamic +bin_PROGRAMS = gmixvm +gmixvm_SOURCES = gmixvm.c mixgtk.h mixgtk.c \ + mixgtk_config.h mixgtk_config.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 \ + mixgtk_fontsel.h mixgtk_fontsel.c \ + mixgtk_wm.h mixgtk_wm.c +endif diff --git a/mixgtk/gmixvm.c b/mixgtk/gmixvm.c new file mode 100644 index 0000000..150c891 --- /dev/null +++ b/mixgtk/gmixvm.c @@ -0,0 +1,124 @@ +/* -*-c-*- -------------- gmixvm.c : + * Main function of the mix gtk front-end + * ------------------------------------------------------------------ + * $Id: gmixvm.c,v 1.6 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include "mixgtk.h" + +static gboolean initfile_ = TRUE; + +#ifdef MAKE_GUILE +# include +# include "mixgtk_cmd_dispatcher.h" +static void +inner_main_ (int argc, char *argv[]) +{ + mixgtk_init (argc, argv); + mixguile_set_cmd_dispatcher (mixgtk_cmd_dispatcher_get_mix_dispatcher ()); + mixguile_load_bootstrap (initfile_); + mixgtk_main (); + mixgtk_release (); +} +#endif + +#ifdef HAVE_GETOPT_LONG +# include +#else +# include +#endif /* HAVE_GETOPT_LONG */ + +enum { + VER_OPT = 'v', + NOINIT_OPT = 'q', + HELP_OPT = 'h', + USAGE_OPT = 'u' +}; + +static const char *options_ = "vqhu"; + +static struct option long_options_[] = +{ + {"version", no_argument, 0, VER_OPT}, + {"help", no_argument, 0, HELP_OPT}, + {"usage", no_argument, 0, USAGE_OPT}, + {"noinit", no_argument, 0, NOINIT_OPT}, + {0, 0, 0, 0} +}; + +static void print_usage_ (const gchar *prog) +{ + static const char *usage_ = + "Usage: %s [-vhuq] [--version] [--help] [--usage] [--noinit]\n"; + fprintf (stderr, usage_, prog); +} + +int +main(int argc, char *argv[]) +{ + int c; + + const char *prog_name = argv[0]; + + 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 VER_OPT: + mix_print_license (_("gmixvm, GTK MIX virtual machine")); + return EXIT_SUCCESS; + case NOINIT_OPT: + initfile_ = FALSE; + break; + case HELP_OPT: + case USAGE_OPT: + print_usage_ (prog_name); + return EXIT_SUCCESS; + case '?': + print_usage_ (prog_name); + return EXIT_FAILURE; + default: + g_assert_not_reached (); + break; + } + } + +#ifdef MAKE_GUILE + mixguile_enter (argc, argv, inner_main_); +#else + if (!mixgtk_init (argc, argv)) return EXIT_FAILURE; + mixgtk_main (); + mixgtk_release (); +#endif + + return EXIT_SUCCESS; +} diff --git a/mixgtk/mixgtk.c b/mixgtk/mixgtk.c new file mode 100644 index 0000000..eddb528 --- /dev/null +++ b/mixgtk/mixgtk.c @@ -0,0 +1,79 @@ +/* -*-c-*- -------------- mixgtk.c : + * Main functions of the mix gtk front-end + * ------------------------------------------------------------------ + * $Id: mixgtk.c,v 1.19 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include + +#include "mixgtk_widgets.h" + +#include "mixgtk_cmd_dispatcher.h" +#include "mixgtk_input.h" +#include "mixgtk_config.h" +#include "mixgtk_wm.h" +#include "mixgtk.h" + +/* initialise the app */ +gboolean +mixgtk_init (int argc, char *argv[]) +{ + mix_init_lib (); + + gtk_init (&argc, &argv); + + if (!mixgtk_config_load ()) + { + g_error (_("Unable to load gmixvm configuration")); + } + + if (!mixgtk_widget_factory_init ()) + { + g_error (_("Unable to initialise application: missing glade file")); + return FALSE; + } + + if (!mixgtk_wm_init ()) + { + g_error (_("Unable to initialise application\n")); + return FALSE; + } + + mixgtk_input_init (); + + return TRUE; +} + +/* main loop */ +void +mixgtk_main (void) +{ + gtk_main (); +} + +/* clean up */ +void +mixgtk_release (void) +{ + if (mixgtk_config_is_autosave ()) mixgtk_config_save (); + mix_vm_cmd_dispatcher_delete (mixgtk_cmd_dispatcher_get_mix_dispatcher ()); + mix_release_lib (); +} diff --git a/mixgtk/mixgtk.glade b/mixgtk/mixgtk.glade new file mode 100644 index 0000000..f16f441 --- /dev/null +++ b/mixgtk/mixgtk.glade @@ -0,0 +1,3913 @@ + + + + + + + gmixvm + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 650 + 550 + True + False + gmixvm-main + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + 2 + True + False + 2 + + + + True + + + + True + _File + True + + + + + + + True + Load a MIX file + _Load... + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Edit a MIXAL source file + _Edit... + True + + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Compile a MIXAL source file + _Compile... + True + + + + + + True + gtk-execute + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + Exit application + E_xit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + De_bug + True + + + + + + + True + Run program + _Run + True + + + + + + True + gtk-go-forward + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Execute next instruction + _Next + True + + + + + + True + gtk-goto-last + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Clear all set breakpoints + _Clear breakpoints + True + + + + + + True + gtk-clear + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Show the symbol table + _Symbols... + True + + + + + + True + gtk-index + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + Vie_w + True + + + + + + + True + _Toolbars + True + False + + + + + + True + _Detached windows + True + + + + True + gtk-dnd-multiple + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _Virtual machine + True + False + + + + + + True + _Source + True + False + + + + + + True + _Devices + True + False + + + + + + + + + + + + + + True + S_ettings + True + + + + + + + True + Change _font + True + + + + True + gtk-select-font + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _Virtual machine + True + + + + + + + True + _Source + True + + + + + + + True + Command _prompt + True + + + + + + + True + Command l_og + True + + + + + + + True + _Devices + True + + + + + + + True + Symbol _list + True + + + + + + + True + + + + + + True + Change all fonts at once + _All + True + + + + + + + + + + + True + Change format of binary devices output + _Device output... + True + + + + + True + gtk-zoom-100 + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + De_vices dir... + True + + + + + True + gtk-home + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + E_xternal programs... + True + + + + + True + gtk-preferences + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + Save current settings + _Save + True + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Toogle save settings on exit + Save on _exit + True + False + + + + + + + + + + + True + _Help + True + + + + + + + True + _About... + True + + + + + True + gtk-help + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + True + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_ICONS + True + True + + + + True + Load MIX program + Open + True + gtk-open + True + True + True + + + + False + True + + + + + + True + Compile MIXAL source + Compile + True + gtk-execute + True + True + True + + + + False + True + + + + + + True + Edit MIXAL source + Edit + True + gtk-justify-fill + True + True + True + + + + False + True + + + + + + True + Run + Run + True + gtk-go-forward + True + True + True + + + + False + True + + + + + + True + Next + Next + True + gtk-goto-last + True + True + True + + + + False + True + + + + + + True + Clear breakpoints + Clear + True + gtk-clear + True + True + True + + + + False + True + + + + + + True + Symbol table + Symbols + True + gtk-index + True + True + True + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + Device directory + Devdir + True + gtk-home + True + True + False + + + + False + True + + + + + + True + Output format + Format + True + gtk-zoom-100 + True + True + False + + + + False + True + + + + + + True + External programs + Programs + True + gtk-properties + True + True + False + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + Detach window + Detach + True + gtk-dnd-multiple + True + True + False + + + + False + True + + + + + + True + Attach all windows + + True + gtk-dnd + True + True + True + + + + False + True + + + + + + + 3 + False + False + + + + + + True + True + 1 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + False + True + + + + + + True + False + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 3 + 4 + 0 + + + + + + 0 + True + True + + + + + + True + Enter MIXVM command here + True + True + True + True + 0 + + True + * + False + + + + + 0 + False + False + + + + + True + True + + + + + 0 + True + True + + + + + + True + True + + + 0 + False + False + + + + + + + + Enter value + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + + True + True + True + gtk-clear + True + GTK_RELIEF_NORMAL + False + 0 + + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + False + GTK_PACK_END + + + + + + 5 + True + + + + 0 + 0 + True + True + True + GDK_KEY_PRESS_MASK + True + True + 0 + 0 + True + * + False + 28 + + + + 88 + 64 + + + + + + 0 + 0 + True + True + GDK_KEY_PRESS_MASK + True + True + 2 + 0 + True + * + False + 3 + + + + 144 + 32 + + + + + + 0 + 0 + True + True + GDK_BUTTON_PRESS_MASK + True + True + 2 + 0 + True + * + False + 3 + + + + 176 + 32 + + + + + + 0 + 0 + True + True + GDK_KEY_PRESS_MASK + True + True + 2 + 0 + True + * + False + 3 + + + + 208 + 32 + + + + + + 0 + 0 + True + True + GDK_KEY_PRESS_MASK + True + True + 2 + 0 + True + * + False + 3 + + + + 238 + 32 + + + + + + 0 + 0 + True + True + GDK_KEY_PRESS_MASK + True + True + 2 + 0 + True + * + False + 3 + + + + 112 + 32 + + + + + + 0 + 0 + True + True + GDK_KEY_PRESS_MASK + True + True + 1 + + + True + * + False + 2 + + + + 88 + 32 + + + + + + 0 + 0 + True + Decimal + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 14 + 68 + + + + + + 0 + 0 + True + Bytes + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 15 + 36 + + + + + + 0 + 0 + True + Enter value + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 112 + 8 + + + + + 0 + True + True + + + + + + + + MDK + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + True + 250 + 150 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + 250 + 150 + 0 0 250 0 225 250 + 0 0 150 0 135 150 + + + + 0 + 0 + True + GNU MIX Development Kit + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 56 + 24 + + + + + + 52 + 16 + True + label223 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 96 + 48 + + + + + + 0 + 0 + True + Copyright (C) 2001, 2002, 2003 , 2004 +Free Software Foundation, Inc. + +Please, send bug reports to +bug-mdk@gnu.org + False + False + GTK_JUSTIFY_CENTER + True + False + 0.5 + 0.5 + 0 + 0 + + + 24 + 80 + + + + + + + + Go to memory cell + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 12 + True + False + 0 + + + + True + Go to address: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + True + True + True + True + 0 + + True + * + True + + + 10 + False + False + + + + + 0 + False + False + + + + + + + + 4 + Select Font + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + + + + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + + + + 4 + True + abcdefghijk ABCDEFGHIJK + + + 0 + True + True + + + + + + Device output format + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + 320 + 140 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + gtk-apply + True + GTK_RELIEF_NORMAL + True + -10 + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + + + + 0 + 0 + True + Set all devices to current format + True + S_et all + True + GTK_RELIEF_NORMAL + True + + + + 233 + 31 + + + + + + 0 + 0 + True + Device + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 24 + 10 + + + + + + 0 + 0 + True + Format + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 24 + 38 + + + + + + 183 + 25 + True + tape0 +tape1 +tape2 +tape3 +tape4 +tape5 +tape6 +tape7 +disk0 +disk1 +disk2 +disk3 +disk4 +disk5 +disk6 +disk7 + + + + 90 + 2 + + + + + + 0 + 0 + True + Show output as MIX words + True + Word + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 89 + 34 + + + + + + 0 + 0 + True + Show output as decimal numbers + True + Decimal + True + GTK_RELIEF_NORMAL + True + False + False + True + wordradio + + + + 154 + 34 + + + + + 0 + True + False + GTK_PACK_END + + + + + + + + External programs + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + True + 0 + + + + True + + + + 0 + 0 + True + True + True + True + 0 + xterm -e vi %s + True + * + False + + + 256 + 12 + + + + + + 0 + 0 + True + Editor command (e.g xterm -e vi %s) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 8 + 15 + + + + + 0 + True + True + + + + + + True + + + + 0 + 0 + True + True + True + True + 0 + mixasm %s + True + * + False + + + 255 + 4 + + + + + + 0 + 0 + True + MIX sssembler command (e.g. mixasm %s) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 8 + 8 + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + Symbol table + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 245 + 265 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + GTK_RELIEF_NORMAL + True + 0 + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Close + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + True + True + True + + + + + 0 + True + True + + + + + + + + MIXAL source + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 570 + 225 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + 2 + True + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_ICONS + True + True + + + + True + Run + Run + True + gtk-go-forward + True + True + True + + + + False + True + + + + + + True + Next + Step + True + gtk-goto-last + True + True + True + + + + False + True + + + + + + True + Clear breakpoints + Clear + True + gtk-clear + True + True + True + + + + False + True + + + + + + True + Symbol table + Symbols + True + gtk-index + True + True + True + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + Source code font + Font + True + gtk-select-font + True + True + True + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + Attach window + + True + gtk-dnd + True + True + True + + + False + True + + + + + + + 0 + False + False + + + + + + True + False + 0 + + + + + + + 0 + True + True + + + + + + True + True + + + 0 + False + False + + + + + + + + Devices + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 550 + 250 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + 2 + True + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_ICONS + True + True + + + + True + Device directory + Directory + True + gtk-home + True + True + True + + + + False + True + + + + + + True + Output format + Output + True + gtk-zoom-100 + True + True + True + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + Output font + Font + True + gtk-select-font + True + True + True + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + + True + gtk-dnd + True + True + True + + + False + True + + + + + + + 0 + False + False + + + + + + True + False + 0 + + + + + + + 0 + True + True + + + + + + + + Devices directory + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + False + GTK_PACK_END + + + + + + 25 + True + False + 11 + + + + True + Directory + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + True + 0 + + True + * + False + + + 0 + True + True + + + + + + True + True + gtk-open + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + Virtual machine + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 268 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + True + False + 0 + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_ICONS + True + True + + + + True + Font + True + gtk-select-font + True + True + True + + + + False + True + + + + + + True + True + True + True + + + False + False + + + + + + True + + True + gtk-dnd + True + True + True + + + False + True + + + + + + + 0 + False + False + + + + + + 5 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + 1 + True + False + 1 + + + + 2 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 8 + True + 3 + 6 + False + 6 + 11 + + + + 0 + 0 + True + A + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + 0 + 0 + True + I1 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + 0 + 0 + True + I2 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + + 0 + 0 + True + True + True + False + True + 0 + + True + * + False + 19 + + + + 1 + 2 + 0 + 1 + + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 3 + 4 + 1 + 2 + + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 3 + 4 + 0 + 1 + + + + + + + + 0 + 0 + True + X + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + 16 + 16 + True + I3 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 2 + 3 + 2 + 3 + fill + + + + + + + 0 + 0 + True + I4 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 4 + 5 + 0 + 1 + fill + + + + + + + 16 + 16 + True + I5 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 4 + 5 + 1 + 2 + fill + + + + + + + 16 + 16 + True + I6 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 4 + 5 + 2 + 3 + fill + + + + + + + 0 + 0 + True + J + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 19 + + + + 1 + 2 + 1 + 2 + + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 5 + 6 + 0 + 1 + + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 5 + 6 + 1 + 2 + + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 5 + 6 + 2 + 3 + + + + + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 3 + 4 + 2 + 3 + + + + + + + + True + False + 0 + + + + 0 + 0 + True + True + False + True + 0 + + True + * + False + 9 + + + + 0 + False + False + + + + + + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + + + True + Registers + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 2 + 0 + + + label_item + + + + + 5 + False + True + + + + + + True + False + 0 + + + + 2 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 1 + True + False + 5 + + + + 2 + 0 + 0 + True + Greater + True + G + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + 2 + 0 + 0 + True + Equal + True + E + True + GTK_RELIEF_NORMAL + True + False + False + True + greater_radio + + + + 0 + False + False + + + + + + 2 + 0 + 0 + True + Lesser + True + L + True + GTK_RELIEF_NORMAL + True + False + False + True + greater_radio + + + + 0 + False + False + + + + + + 7 + True + + + 0 + False + False + + + + + + True + True + Overflow + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + + + True + Flags + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 2 + 0 + + + label_item + + + + + 0 + False + False + + + + + + + + + + 2 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 4 + True + False + 1 + + + + 0 + 0 + True + True + False + True + 4 + 0 + True + * + False + 6 + + + 5 + False + False + + + + + + True + View loc address + True + GTK_RELIEF_NORMAL + True + + + + + True + gtk-jump-to + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 1 + False + False + + + + + + + + True + Location + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 2 + 0 + + + label_item + + + + + 0 + False + False + GTK_PACK_END + + + + + 5 + False + True + + + + + + 2 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + True + 5 + + + + 0 + 0 + True + Uptime: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + 0 + 0 + True + 00000000 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 5 + 0 + + + 0 + False + False + + + + + + 0 + 0 + True + Elapsed: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 3 + False + False + + + + + + 0 + 0 + True + 000000 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 5 + 0 + + + 0 + False + False + + + + + + 0 + 0 + True + Program: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 2 + False + False + + + + + + 0 + 0 + True + 000000 + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 5 + 0 + + + 0 + False + False + + + + + + + + True + Times + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 2 + 0 + + + label_item + + + + + 5 + False + True + + + + + 2 + False + False + + + + + + 7 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + 5 + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + GDK_BUTTON_PRESS_MASK + True + True + False + True + + + + + + + + True + Memory + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 2 + 0 + + + label_item + + + + + 3 + True + True + GTK_PACK_END + + + + + + + + True + MIX Virtual Machine + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 2 + 0 + + + label_item + + + + + 0 + True + True + + + + + + + + True + MIX Console input + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + 0 + False + True + GTK_PACK_END + + + + + + 3 + True + True + 0 + + + + True + Enter up to 70 characters + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + True + True + 70 + + True + * + True + 70 + + + 0 + False + False + + + + + 0 + False + False + + + + + + + diff --git a/mixgtk/mixgtk.gladep b/mixgtk/mixgtk.gladep new file mode 100644 index 0000000..40a311a --- /dev/null +++ b/mixgtk/mixgtk.gladep @@ -0,0 +1,9 @@ + + + + + Mixgtk + mixgtk + . + FALSE + diff --git a/mixgtk/mixgtk.h b/mixgtk/mixgtk.h new file mode 100644 index 0000000..913c245 --- /dev/null +++ b/mixgtk/mixgtk.h @@ -0,0 +1,49 @@ +/* -*-c-*- ---------------- mixgtk.h : + * Gmixvm initialisation and cleanup functions + * ------------------------------------------------------------------ + * Last change: Time-stamp: <2001-04-29 12:06:48 jao> + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_H +#define MIXGTK_H + +#include +#include + +/* the app files directory */ +#define MIXGTK_FILES_DIR ".mdk" + +/* initialise the app */ +extern gboolean +mixgtk_init (int argc, char *argv[]); + +/* enter the main mixgtk loop */ +extern void +mixgtk_main (void); + +/* clean up */ +extern void +mixgtk_release (void); + + + +#endif /* MIXGTK_H */ + diff --git a/mixgtk/mixgtk_cmd_dispatcher.c b/mixgtk/mixgtk_cmd_dispatcher.c new file mode 100644 index 0000000..dbb2909 --- /dev/null +++ b/mixgtk/mixgtk_cmd_dispatcher.c @@ -0,0 +1,547 @@ +/* -*-c-*- -------------- mixgtk_cmd_dispatcher.c : + * Implementation of the functions declared in mixgtk_cmd_dispatcher.h + * ------------------------------------------------------------------ + * $Id: mixgtk_cmd_dispatcher.c,v 1.24 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_LIBHISTORY +# include +#endif + +#ifdef MAKE_GUILE +# include +#endif + +#include +#include +#include "mixgtk_mixvm.h" +#include "mixgtk_mixal.h" +#include "mixgtk_fontsel.h" +#include "mixgtk_config.h" +#include "mixgtk_cmd_dispatcher.h" + + +/* a mix vm command dispatcher */ +typedef struct mixgtk_dispatch_ +{ + mix_vm_cmd_dispatcher_t *dispatcher; /* the underlying cmd dispatcher */ + FILE *out; /* the dispatcher's output file */ + int fildes[2]; /* pipe for communication with the dispatcher */ + GtkWidget *prompt; /* the command prompt widget */ + GtkWidget *log; /* the dispatcher's messages echo area */ + GtkWidget *status; /* the status bar widget */ + guint context; /* context of the status bar messages */ + gchar *last_file; +} mixgtk_dispatch_data_t; + +static struct mixgtk_dispatch_ dis_data_ = {NULL}; + +static GtkWidget *ext_dlg_ = NULL; +static GtkWidget *ed_entry_ = NULL; +static GtkWidget *asm_entry_ = NULL; + +static const gchar *ED_NAME_ = "editor_entry"; +static const gchar *ASM_NAME_ = "mixasm_entry"; + +static const gchar *TITLE_FORMAT_ = "gmixvm - %s"; + +static void +log_command_ (mixgtk_dispatch_data_t *dis, const gchar *cmd) +{ + GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis->log)); + GtkTextIter end; + + gtk_text_buffer_get_end_iter (buf, &end); + gtk_text_buffer_place_cursor (buf, &end); + gtk_text_buffer_insert_at_cursor (buf, "MIX> ", -1); + gtk_text_buffer_insert_at_cursor (buf, cmd, -1); + gtk_text_buffer_insert_at_cursor (buf, "\n", -1); + +#ifdef HAVE_LIBHISTORY + add_history ((char *)cmd); +/* history_search ((char *)cmd, 0); */ + history_set_pos (history_base + history_length - 1); +#endif +} + +static void +flush_log_ (mixgtk_dispatch_data_t *dis) +{ + enum {BLKSIZE = 100}; + static gchar BUFFER[BLKSIZE]; + + GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis->log)); + GtkTextMark *mark; + GtkTextIter end; + ssize_t k; + + gtk_text_buffer_get_end_iter (buffer, &end); + gtk_text_buffer_place_cursor (buffer, &end); + + fflush (dis->out); + while ((k = read (dis->fildes[0], BUFFER, BLKSIZE)) != 0) + { + if (k == -1 && errno != EINTR) break; + if (k != -1) + gtk_text_buffer_insert_at_cursor (buffer, BUFFER, k); + } + + mark = gtk_text_buffer_get_insert (buffer); + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (dis->log), mark, 0, + TRUE, 0, 0); +} + +/* hooks */ +static void +global_post_hook_ (mix_vm_cmd_dispatcher_t *dis, + mix_vm_command_t cmd, const gchar *arg, gpointer data) +{ + flush_log_ ((mixgtk_dispatch_data_t *)data); + 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)) + { + GtkWindow *mainw = + GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN)); + + if (dis_data_.last_file) g_free (dis_data_.last_file); + dis_data_.last_file = g_strdup_printf (TITLE_FORMAT_, arg); + gtk_window_set_title (mainw, dis_data_.last_file); + + mixgtk_mixal_load_file (); + mixgtk_mixal_update (); + mixgtk_mixal_update_bp_all (); + + 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, + dis_data_.last_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_post_hook (dis_data_.dispatcher, + global_post_hook_, + (gpointer)(&dis_data_)); + 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); +} + +/* configuration stuff */ +static const gchar *EDITOR_KEY_ = "Editor"; +static const gchar *MIXASM_KEY_ = "Mixasm"; + +static void +read_config_ (void) +{ + const gchar *editor = mixgtk_config_get (EDITOR_KEY_); + const gchar *assem = mixgtk_config_get (MIXASM_KEY_); + + if (!editor) + { + static const gchar *ENV[] = {"MDK_EDITOR", "X_EDITOR", NULL}; + gchar *edit = NULL; + int k = 0; + while (!edit && ENV[k]) edit = getenv (ENV[k++]); + if (edit) edit = g_strconcat (edit, " %s", NULL); + else edit = g_strdup ("xterm -e vi %s"); + mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, edit); + g_free (edit); + } + else + { + mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, editor); + } + if (!assem) assem = "mixasm %s"; + mix_vm_cmd_dispatcher_set_assembler (dis_data_.dispatcher, assem); + +} + +void +on_external_programs_activate () +{ + if (!ext_dlg_) + { + ext_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_EXTERNPROG_DIALOG); + g_return_if_fail (ext_dlg_ != NULL); + ed_entry_ = mixgtk_widget_factory_get_child_by_name + (MIXGTK_EXTERNPROG_DIALOG, ED_NAME_); + g_assert (ed_entry_); + asm_entry_ = mixgtk_widget_factory_get_child_by_name + (MIXGTK_EXTERNPROG_DIALOG, ASM_NAME_); + g_assert (asm_entry_); + } + gtk_entry_set_text (GTK_ENTRY (ed_entry_), + mix_vm_cmd_dispatcher_get_editor (dis_data_.dispatcher)); + gtk_entry_set_text (GTK_ENTRY (asm_entry_), + mix_vm_cmd_dispatcher_get_assembler + (dis_data_.dispatcher)); + gtk_widget_show (ext_dlg_); + if (gtk_dialog_run (GTK_DIALOG (ext_dlg_)) == GTK_RESPONSE_OK) + { + const gchar *value = gtk_entry_get_text (GTK_ENTRY (ed_entry_)); + mix_vm_cmd_dispatcher_set_editor (dis_data_.dispatcher, value); + mixgtk_config_update (EDITOR_KEY_, value); + value = gtk_entry_get_text (GTK_ENTRY (asm_entry_)); + mix_vm_cmd_dispatcher_set_assembler (dis_data_.dispatcher, value); + mixgtk_config_update (MIXASM_KEY_, value); + } + + gtk_widget_hide (ext_dlg_); +} + +/* initialise the command dispatcher */ +gboolean +mixgtk_cmd_dispatcher_init (mixgtk_dialog_id_t top) +{ + static gboolean restart = FALSE; + gchar *text = NULL; + + ext_dlg_ = NULL; + ed_entry_ = NULL; + asm_entry_ = NULL; + + dis_data_.prompt = + mixgtk_widget_factory_get (top, MIXGTK_WIDGET_PROMPT); + g_return_val_if_fail (dis_data_.prompt != NULL, FALSE); + + if (dis_data_.log) + text = gtk_editable_get_chars (GTK_EDITABLE (dis_data_.log), 0, -1); + + dis_data_.log = + mixgtk_widget_factory_get (top, MIXGTK_WIDGET_LOG); + + g_return_val_if_fail (dis_data_.log != NULL, FALSE); + + if (text) + { + gtk_text_buffer_insert_at_cursor + (gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis_data_.log)), text, -1); + g_free (text); + } + + if (!dis_data_.dispatcher) + { + static const gchar *HISTORY_FILE = "gmixvm.history"; + static gint HISTORY_SIZE = 100; + mix_config_t *config = mixgtk_config_get_mix_config (); + + int r = pipe (dis_data_.fildes); + g_return_val_if_fail (r == 0, FALSE); + /* connect stdout/stderr to the pipe's write end */ + if (dup2 (dis_data_.fildes[1], STDOUT_FILENO) == -1 + || dup2 (dis_data_.fildes[1], STDOUT_FILENO) == -1) + return FALSE; + dis_data_.out = fdopen (dis_data_.fildes[1], "w"); + g_return_val_if_fail (dis_data_.out != NULL, FALSE); + r = fcntl (dis_data_.fildes[0], F_GETFL, 0); + g_return_val_if_fail (r != -1, FALSE); + r |= O_NONBLOCK; + r = fcntl(dis_data_.fildes[0], F_SETFL, r); + g_return_val_if_fail (r != -1, FALSE); + + if (!mix_config_get_history_file (config)) + mix_config_set_history_file (config, HISTORY_FILE); + if (mix_config_get_history_size (config) == 0) + mix_config_set_history_size (config, HISTORY_SIZE); + + dis_data_.dispatcher = + mix_vm_cmd_dispatcher_new_with_config (dis_data_.out, + dis_data_.out, + config); + mix_vm_cmd_dispatcher_print_time (dis_data_.dispatcher, FALSE); + + install_hooks_ (); + } + + dis_data_.status = + mixgtk_widget_factory_get (MIXGTK_MAIN, 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 (!restart) read_config_ (); + if (dis_data_.last_file) + gtk_window_set_title + (GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN)), + dis_data_.last_file); + + mixgtk_fontsel_set_font (MIX_FONT_LOG, dis_data_.log); + mixgtk_fontsel_set_font (MIX_FONT_PROMPT, dis_data_.prompt); + + restart = TRUE; + return TRUE; +} + +/* dispatch an externally provided command */ +#ifdef MAKE_GUILE +static gboolean +try_guile_ (const gchar *command) +{ + if (command && command[0] == '(' && command[strlen (command) - 1] == ')') + { + mixguile_interpret_command (command); + return TRUE; + } + return FALSE; +} +#else +# define try_guile_(ignored) FALSE +#endif + +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); + log_command_ (&dis_data_, command); + if (!try_guile_ (command)) + mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, command); + gtk_entry_set_text (GTK_ENTRY (entry), ""); +} + +/* 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 */ +mix_vm_t * +mixgtk_cmd_dispatcher_get_vm (void) +{ + return (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (dis_data_.dispatcher); +} + +/* get the current source file */ +const gchar * +mixgtk_cmd_dispatcher_get_src_path (void) +{ + return mix_vm_cmd_dispatcher_get_src_file_path (dis_data_.dispatcher); +} + +/* get the mix cmd dispatcher */ +mix_vm_cmd_dispatcher_t * +mixgtk_cmd_dispatcher_get_mix_dispatcher (void) +{ + return dis_data_.dispatcher; +} + +/* process commands */ +void +complete_command_ (void) +{ + GtkEntry *entry = GTK_ENTRY (dis_data_.prompt); + gchar *prefix = NULL; + const gchar *text = gtk_entry_get_text (entry); + const GList *cmds = + mix_vm_cmd_dispatcher_complete (dis_data_.dispatcher, text, &prefix); + + if (prefix != NULL) + { + GtkTextBuffer *buf = + gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis_data_.log)); + + gtk_entry_set_text (entry, prefix); + if (g_list_length ((GList *)cmds) > 1) + { + static gchar BUFFER[25]; + gint k = 0; + gtk_text_buffer_insert_at_cursor (buf, "Completions:\n", -1); + while (cmds) + { + g_snprintf (BUFFER, 25, "%-12s", (const char*)cmds->data); + ++k; + gtk_text_buffer_insert_at_cursor (buf, BUFFER, -1); + if (k%5 == 0) + gtk_text_buffer_insert_at_cursor (buf, "\n", -1); + + cmds = cmds->next; + } + if (k%5 != 0) + gtk_text_buffer_insert_at_cursor (buf, "\n", -1); + } + else + { + gint pos = strlen (prefix); + gtk_editable_insert_text (GTK_EDITABLE (entry), " ", 1, &pos); + } + flush_log_ (&dis_data_); + g_free (prefix); + } +} + +int +on_command_prompt_key_press_event (GtkEntry *w, GdkEventKey *e, gpointer d) +{ + guint key = e->keyval; + gboolean result = FALSE; + +#ifdef HAVE_LIBHISTORY + HIST_ENTRY *entry = NULL; + if (key == GDK_Up) + { + entry = previous_history (); + if (entry && entry->line) + gtk_entry_set_text (w, entry->line); + result = TRUE; + } + if (key == GDK_Down) + { + entry = next_history (); + if (entry && entry->line) + gtk_entry_set_text (w, entry->line); + result = TRUE; + } +#endif + + if (key == GDK_Tab) + { + complete_command_ (); + result = TRUE; + } + + if (result) gtk_editable_set_position (GTK_EDITABLE (w), -1); + + return result; +} + +void +on_command_prompt_activate (GtkEntry *prompt, gpointer data) +{ + gchar *text = + g_strstrip (gtk_editable_get_chars (GTK_EDITABLE (prompt), 0, -1)); + if (text && *text) + { + log_command_ (&dis_data_, text); + if (!try_guile_ (text)) + mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text); + gtk_entry_set_text (prompt, ""); + } + g_free (text); +} + +void +on_log_font_activate () +{ + GtkWidget *w[] = { dis_data_.log }; + mixgtk_fontsel_query_font (MIX_FONT_LOG, w, 1); +} + +void +on_prompt_font_activate () +{ + GtkWidget *w[] = { dis_data_.prompt }; + mixgtk_fontsel_query_font (MIX_FONT_PROMPT, w, 1); +} + +void +mixgtk_cmd_dispatcher_update_fonts (void) +{ + mixgtk_fontsel_set_font (MIX_FONT_LOG, dis_data_.log); + mixgtk_fontsel_set_font (MIX_FONT_PROMPT, dis_data_.prompt); +} diff --git a/mixgtk/mixgtk_cmd_dispatcher.h b/mixgtk/mixgtk_cmd_dispatcher.h new file mode 100644 index 0000000..25ca240 --- /dev/null +++ b/mixgtk/mixgtk_cmd_dispatcher.h @@ -0,0 +1,61 @@ +/* -*-c-*- ---------------- mixgtk_cmd_dispatcher.h : + * functions to access the command dispatcher + * ------------------------------------------------------------------ + * $Id: mixgtk_cmd_dispatcher.h,v 1.6 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_CMD_DISPATCHER_H +#define MIXGTK_CMD_DISPATCHER_H + +#include +#include +#include "mixgtk_widgets.h" + +/* initialise the command dispatcher */ +extern gboolean +mixgtk_cmd_dispatcher_init (mixgtk_dialog_id_t top); + +extern void +mixgtk_cmd_dispatcher_update_fonts (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); + +/* get the current source file */ +extern const gchar * +mixgtk_cmd_dispatcher_get_src_path (void); + +/* get the mix cmd dispatcher */ +extern mix_vm_cmd_dispatcher_t * +mixgtk_cmd_dispatcher_get_mix_dispatcher (void); + + +#endif /* MIXGTK_CMD_DISPATCHER_H */ + diff --git a/mixgtk/mixgtk_config.c b/mixgtk/mixgtk_config.c new file mode 100644 index 0000000..275d182 --- /dev/null +++ b/mixgtk/mixgtk_config.c @@ -0,0 +1,113 @@ +/* -*-c-*- -------------- mixgtk_config.c : + * Implementation of the functions declared in mixgtk_config.h + * ------------------------------------------------------------------ + * $Id: mixgtk_config.c,v 1.10 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#include +#include +#include +#include "mixgtk.h" +#include "mixgtk_config.h" + +static const gchar *MIXGTK_CONFIG_FILE_ = "gmixvm.config"; +static const gchar *SHOW_TB_KEY = "Toolbars"; +static const gchar *TB_YES = "Yes"; +static const gchar *TB_NO = "No"; + +static mix_config_t *config_ = NULL; + +/* load configuration */ +gboolean +mixgtk_config_load (void) +{ + if (config_ == NULL) + { + gchar *cdir = g_strconcat (g_get_home_dir (), G_DIR_SEPARATOR_S, + MIXGTK_FILES_DIR, NULL); + config_ = mix_config_new (cdir, MIXGTK_CONFIG_FILE_); + g_free (cdir); + } + return (config_ != NULL); +} + +/* get mixlib config */ +mix_config_t * +mixgtk_config_get_mix_config (void) +{ + return config_; +} + +/* autosave state */ +gboolean +mixgtk_config_is_autosave (void) +{ + return mix_config_is_autosave (config_); +} + +void +mixgtk_config_set_autosave (gboolean autosave) +{ + mix_config_set_autosave (config_, autosave); +} + +/* update config item */ +void +mixgtk_config_update (const gchar *key, const gchar *value) +{ + mix_config_update (config_, key, value); +} + +/* get config item */ +const gchar * +mixgtk_config_get (const gchar *key) +{ + return mix_config_get (config_, key); +} + +void +mixgtk_config_remove (const char *key) +{ + mix_config_remove (config_, key); +} + +/* save configuration */ +void +mixgtk_config_save (void) +{ + mix_config_save (config_); +} + +gboolean +mixgtk_config_show_toolbars (void) +{ + const gchar *show = mixgtk_config_get (SHOW_TB_KEY); + return (!show || !strcmp (show, TB_YES)); +} + +void +mixgtk_config_set_show_toolbars (gboolean show) +{ + mixgtk_config_update (SHOW_TB_KEY, show? TB_YES : TB_NO); +} diff --git a/mixgtk/mixgtk_config.h b/mixgtk/mixgtk_config.h new file mode 100644 index 0000000..7c3f548 --- /dev/null +++ b/mixgtk/mixgtk_config.h @@ -0,0 +1,70 @@ +/* -*-c-*- ---------------- mixgtk_config.h : + * Configuration functions declarations. + * ------------------------------------------------------------------ + * $Id: mixgtk_config.h,v 1.7 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_CONFIG_H +#define MIXGTK_CONFIG_H + +#include +#include + +/* load configuration */ +extern gboolean +mixgtk_config_load (void); + +/* get mix config */ +extern mix_config_t * +mixgtk_config_get_mix_config (void); + +/* autosave state */ +extern gboolean +mixgtk_config_is_autosave (void); + +extern void +mixgtk_config_set_autosave (gboolean autosave); + +/* update config item */ +extern void +mixgtk_config_update (const gchar *key, const gchar *value); + +/* get config item */ +extern const gchar * +mixgtk_config_get (const gchar *key); + +/* remove config item */ +extern void +mixgtk_config_remove (const gchar *key); + +/* save configuration */ +extern void +mixgtk_config_save (void); + +/* shared config params */ +extern gboolean +mixgtk_config_show_toolbars (void); + +extern void +mixgtk_config_set_show_toolbars (gboolean show); + +#endif /* MIXGTK_CONFIG_H */ + diff --git a/mixgtk/mixgtk_device.c b/mixgtk/mixgtk_device.c new file mode 100644 index 0000000..203933c --- /dev/null +++ b/mixgtk/mixgtk_device.c @@ -0,0 +1,625 @@ +/* -*-c-*- ---------------- mixgtk_device.c : + * actual types for mixgtk devices + * ------------------------------------------------------------------ + * $Id: mixgtk_device.c,v 1.26 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include + +#include +#include + +#include "mixgtk.h" +#include "mixgtk_gen_handlers.h" +#include "mixgtk_widgets.h" +#include "mixgtk_fontsel.h" +#include "mixgtk_config.h" +#include "mixgtk_cmd_dispatcher.h" +#include "mixgtk_device.h" + +#define BIN_DEV_COL_ 5 + +static const gchar *DEV_FORMAT_KEY_ = "Device.format"; + +/* device container */ +static GtkNotebook *dev_nb_ = NULL; +/* devdir dialog */ +static GtkWidget *devdir_dlg_ = NULL; +static GtkEntry *devdir_entry_ = NULL; +/* terminal input dialog */ +static GtkWidget *input_dlg_ = NULL; +static GtkEntry *input_dlg_entry_ = NULL; + +/** configuration stuff */ +#define LAST_BIN_DEV_ mix_dev_DISK_7 +static GtkWidget *devdlg_ = NULL; +static GtkWidget *dtoggle_ = NULL; +static GtkWidget *wtoggle_ = NULL; +static GtkWidget *combo_ = NULL; + +/* virtual machine */ +static mix_vm_t *vm_ = NULL; +/* dec settings */ +static gint32 decs_ = 0; +static gint32 new_decs_ = 0; + +/* macros manipulating dec settings */ +#define IS_DEC(flags,type) (((flags) >> (type)) & 1) +#define SET_DEC(flags,type) ((flags) |= (1<<(type))) +#define CLEAR_DEC(flags,type) ((flags) &= ~(1<<(type))) + +/* a mixgtk device */ +struct mixgtk_device_t +{ + mix_device_t device; + GtkWidget *widget; + GtkWidget *scroll; +}; + +struct mixgtk_bin_device_t +{ + struct mixgtk_device_t gtk_device; + guint last_insert; + GtkListStore *store; + gboolean dec; +}; + +/* callbacks for output devices */ +static void +write_char_ (struct mixgtk_device_t *dev, const mix_word_t *block) +{ + enum {MAX_BLOCK = 16, BUFF_SIZE = MAX_BLOCK * 5 + 2}; + static gchar BUFFER[BUFF_SIZE]; + + guint k, j; + GtkTextIter end; + GtkTextBuffer *buffer; + GtkTextMark *mark; + + for (k = 0; k < SIZES_[dev->device.type]; k++) + for (j = 1; j < 6; j++) + { + mix_char_t ch = mix_word_get_byte (block[k], j); + BUFFER[5 * k + j - 1] = mix_char_to_ascii (ch); + } + + BUFFER[5 * k] = '\n'; + BUFFER[5 * k + 1] = '\0'; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dev->widget)); + gtk_text_buffer_get_end_iter (buffer, &end); + gtk_text_buffer_place_cursor (buffer, &end); + gtk_text_buffer_insert_at_cursor (buffer, BUFFER, -1); + mark = gtk_text_buffer_get_insert (buffer); + gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (dev->widget), mark, 0, + TRUE, 0, 0); +} + +static const gchar * +get_word_string_ (mix_word_t w, gboolean dec) +{ + enum {BUFF_SIZE = 17}; + static gchar BUFFER[BUFF_SIZE] = { 0 }; + if (dec) + g_snprintf (BUFFER, BUFF_SIZE, "%s%011ld", + mix_word_is_negative (w)? "-" : "+", + mix_word_magnitude (w)); + else + mix_word_print_to_buffer (w, BUFFER); + return BUFFER; +} + +static void +write_bin_ (struct mixgtk_bin_device_t *dev, const mix_word_t *block) +{ + guint k, col; + gboolean dec = FALSE; + size_t len; + + GtkTreeView *view = GTK_TREE_VIEW (dev->gtk_device.widget); + GtkListStore *store = dev->store; + GtkTreeIter iter; + + g_assert (view); + g_assert (store); + + dec = IS_DEC(decs_, dev->gtk_device.device.type); + + for (k = 0, len = SIZES_[dev->gtk_device.device.type]; + k < len; k += BIN_DEV_COL_) + { + gtk_list_store_append (store, &iter); + for (col = 0; col < BIN_DEV_COL_; ++col) + gtk_list_store_set (store, &iter, + col, get_word_string_ (block[k + col], dec), + col + BIN_DEV_COL_, (guint)block[k + col], + -1); + dev->last_insert++; + } +} + +static gboolean +write_ (mix_device_t *dev, const mix_word_t *block) +{ + struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *) dev; + + if (dev->type != mix_dev_CONSOLE && !(DEF_DEV_VTABLE_->write)(dev, block)) + return FALSE; + + if (MODES_[dev->type] == mix_dev_CHAR) write_char_ (gtkdev, block); + else write_bin_ ((struct mixgtk_bin_device_t *)gtkdev, block); + + gtk_notebook_set_current_page (dev_nb_, + gtk_notebook_page_num (dev_nb_, + gtkdev->scroll)); + + return TRUE; +} + +static gboolean +read_cons_ (mix_word_t *block) +{ + gchar *text; + size_t i, j; + + if (input_dlg_ == NULL) + { + input_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_INPUT_DIALOG); + g_assert (input_dlg_); + input_dlg_entry_ = GTK_ENTRY (mixgtk_widget_factory_get_child_by_name + (MIXGTK_INPUT_DIALOG, "input_entry")); + g_assert (input_dlg_entry_); + } + + gtk_entry_set_text (input_dlg_entry_, ""); + gtk_dialog_run (GTK_DIALOG (input_dlg_)); + gtk_widget_hide (input_dlg_); + text = g_strdup_printf ("%-70s", gtk_entry_get_text (input_dlg_entry_)); + for (i = 0; i < 70; ++i) + for (j = 0; j < 5; ++j) + mix_word_set_byte (block + i, j + 1, + mix_char_to_byte + (mix_ascii_to_char (text[5 * i + j]))); + g_free (text); + return TRUE; +} + +static gboolean +read_ (mix_device_t *dev, mix_word_t *block) +{ + struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *) dev; + + if (dev->type == mix_dev_CONSOLE && !read_cons_ (block)) return FALSE; + + if (dev->type != mix_dev_CONSOLE && !(DEF_DEV_VTABLE_->read)(dev, block)) + return FALSE; + + if (MODES_[dev->type] == mix_dev_CHAR) write_char_ (gtkdev, block); + else write_bin_ ((struct mixgtk_bin_device_t *)gtkdev, block); + + gtk_notebook_set_current_page (dev_nb_, + gtk_notebook_page_num (dev_nb_, + gtkdev->scroll)); + return TRUE; +} + +static gboolean +ioc_ (mix_device_t *dev, mix_short_t cmd) +{ + return (DEF_DEV_VTABLE_->ioc)(dev, cmd); +} + +static gboolean +busy_ (const mix_device_t *dev) +{ + return (DEF_DEV_VTABLE_->busy)(dev); +} + +static void +destroy_ (mix_device_t *dev) +{ + struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *)dev; + if (MODES_[dev->type] == mix_dev_BIN) { + struct mixgtk_bin_device_t * bdev = (struct mixgtk_bin_device_t *)dev; + gtk_list_store_clear (bdev->store); + g_object_unref ((gpointer)bdev->store); + } + (DEF_DEV_VTABLE_->destroy) (dev); + gtk_notebook_remove_page (dev_nb_, + gtk_notebook_page_num (dev_nb_, + gtkdev->scroll)); +} + +static mix_device_vtable_t MIXGTK_VTABLE_ = { + write_, read_, ioc_, busy_, destroy_ +}; + +/* create the gui part of the device */ +static void +mixgtk_device_construct_gui_ (struct mixgtk_device_t *dev) +{ + GtkWidget *label = gtk_label_new (DEF_NAMES_[dev->device.type]); + + g_assert (label); + + dev->scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dev->scroll), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + if (MODES_[dev->device.type] == mix_dev_CHAR) + { + dev->widget = gtk_text_view_new (); + gtk_text_view_set_editable (GTK_TEXT_VIEW (dev->widget), FALSE); + } + else + { + gint k; + struct mixgtk_bin_device_t *bindev = (struct mixgtk_bin_device_t *)dev; + GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); + GType *types = g_new (GType, BIN_DEV_COL_ * 2); + + for (k = 0; k < BIN_DEV_COL_; ++k) + { + types[k] = G_TYPE_STRING; + types[k + BIN_DEV_COL_] = G_TYPE_UINT; + } + + bindev->store = gtk_list_store_newv (BIN_DEV_COL_ * 2, types); + + dev->widget = + gtk_tree_view_new_with_model (GTK_TREE_MODEL (bindev->store)); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dev->widget), FALSE); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (dev->widget), TRUE); + + for (k = 0; k < BIN_DEV_COL_; ++k) + { + gtk_tree_view_append_column + (GTK_TREE_VIEW (dev->widget), + gtk_tree_view_column_new_with_attributes ("", renderer, + "text", k, NULL)); + } + + + g_free (types); + } + + g_assert (dev->widget); + gtk_container_add (GTK_CONTAINER (dev->scroll), dev->widget); + mixgtk_fontsel_set_font (MIX_FONT_DEVICES, dev->widget); + gtk_notebook_append_page (dev_nb_, dev->scroll, label); + gtk_widget_show (label); + gtk_widget_show (dev->scroll); + gtk_widget_show (dev->widget); +} + +static void +redraw_bin_device_ (struct mixgtk_bin_device_t *dev) +{ + if (dev != NULL) + { + GtkTreeModel *store = GTK_TREE_MODEL (dev->store); + GtkTreeIter iter; + gboolean valid; + + g_assert (store); + + valid = + gtk_tree_model_get_iter_first (store, &iter); + + while (valid) + { + gint k; + guint word; + + for (k = 0; k < BIN_DEV_COL_; ++k) + { + gtk_tree_model_get (store, &iter, k + BIN_DEV_COL_, &word, -1); + gtk_list_store_set (GTK_LIST_STORE (store), &iter, + k, get_word_string_ ((mix_word_t)word, + dev->dec), + -1); + } + valid = gtk_tree_model_iter_next (store, &iter); + } + gtk_widget_queue_draw (((struct mixgtk_device_t *)dev)->widget); + } +} + + +/* create a new mixgtk device */ +static mix_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) + { + dev = g_new (struct mixgtk_device_t, 1); + } + else + { + dev = (struct mixgtk_device_t *) g_new (struct mixgtk_bin_device_t, 1); + ((struct mixgtk_bin_device_t *)dev)->last_insert = 0; + } + + construct_device_ (&dev->device, type); + + dev->device.vtable = &MIXGTK_VTABLE_; + + mixgtk_device_construct_gui_ (dev); + + return (mix_device_t *)dev; +} + +/* init default devices */ +GtkWidget * +mixgtk_device_init (mix_vm_t *vm) +{ + g_assert (vm != NULL); + + vm_ = vm; + devdlg_ = NULL; + devdir_dlg_ = NULL; + devdir_entry_ = NULL; + input_dlg_ = NULL; + dtoggle_ = NULL; + wtoggle_ = NULL; + combo_ = NULL; + + if (dev_nb_ == NULL) + { + mix_vm_set_device_factory (vm, mixgtk_device_new_); + + /* read format configuration */ + if (mixgtk_config_get (DEV_FORMAT_KEY_)) + decs_ = atoi (mixgtk_config_get (DEV_FORMAT_KEY_)); + + dev_nb_ = GTK_NOTEBOOK (gtk_notebook_new ()); + gtk_notebook_set_tab_pos (dev_nb_, GTK_POS_RIGHT); + gtk_notebook_set_scrollable (dev_nb_, FALSE); + } + + mixgtk_fontsel_set_font (MIX_FONT_DEVICES, GTK_WIDGET (dev_nb_)); + + return GTK_WIDGET (dev_nb_); +} + +void +mixgtk_device_set_format (mix_device_type_t dev, gboolean dec) +{ + gboolean changed; + + g_return_if_fail (dev < mix_dev_INVALID); + + changed = (dec && !IS_DEC (decs_, dev)) || (!dec && IS_DEC (decs_, dev)); + + if (changed && (MODES_[dev] == mix_dev_BIN)) + { + struct mixgtk_bin_device_t *gdev = + (struct mixgtk_bin_device_t *) mix_vm_get_device (vm_, dev); + + if (gdev != NULL) + { + if (dec) SET_DEC (decs_, dev); else CLEAR_DEC (decs_, dev); + gdev->dec = !(gdev->dec); + redraw_bin_device_ (gdev); + } + } +} + + +static mix_device_type_t +get_device_idx_ (void) +{ + int k; + const gchar *name = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (combo_)->child)); + for (k = 0; k <= LAST_BIN_DEV_; ++k) + if (!strcmp (name, DEF_NAMES_[k])) break; + return k; +} + +static void +init_devform_ (void) +{ + devdlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_DEVFORM_DIALOG); + g_assert (devdlg_); + dtoggle_ = mixgtk_widget_factory_get_child_by_name + (MIXGTK_DEVFORM_DIALOG, "decradio"); + g_assert (dtoggle_); + wtoggle_ = mixgtk_widget_factory_get_child_by_name + (MIXGTK_DEVFORM_DIALOG, "wordradio"); + g_assert (wtoggle_); + combo_ = mixgtk_widget_factory_get_child_by_name + (MIXGTK_DEVFORM_DIALOG, "dev_combo"); + g_assert (combo_); + gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (combo_)->child), FALSE); +} + +void +on_dev_combo_changed () +{ + mix_device_type_t dev = get_device_idx_ (); + if (dev <= LAST_BIN_DEV_) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtoggle_), + IS_DEC (new_decs_, dev)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle_), + !IS_DEC (new_decs_, dev)); + } +} + +void +on_devform_activate () +{ + gint result = GTK_RESPONSE_APPLY; + + if (!devdlg_) init_devform_ (); + new_decs_ = decs_; + + while (result == GTK_RESPONSE_APPLY) + { + //on_dev_combo_changed (); + result = gtk_dialog_run (GTK_DIALOG (devdlg_)); + if (result != GTK_RESPONSE_CANCEL) + { + int k; + gchar value[20]; + for (k = 0; k <= LAST_BIN_DEV_; ++k) + mixgtk_device_set_format (k, IS_DEC (new_decs_, k)); + decs_ = new_decs_; + g_snprintf (value, 20, "%d", decs_); + mixgtk_config_update (DEV_FORMAT_KEY_, value); + } + } + + gtk_widget_hide (devdlg_); +} + +void +on_decradio_toggled (GtkToggleButton *button) +{ + if (gtk_toggle_button_get_active (button)) + SET_DEC (new_decs_, get_device_idx_ ()); + else + CLEAR_DEC (new_decs_, get_device_idx_ ()); +} + +void +on_devset_button_clicked () +{ + static gint32 ON = 0xffff, OFF = 0; + new_decs_ = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dtoggle_)))? + ON : OFF; +} + +void +on_devdir_activate () +{ + static const gchar *DEVDIR_ENTRY_NAME = "devdir_entry"; + if (devdir_dlg_ == NULL) + { + devdir_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_DEVDIR_DIALOG); + g_assert (devdir_dlg_); + devdir_entry_ = GTK_ENTRY + (mixgtk_widget_factory_get_child_by_name (MIXGTK_DEVDIR_DIALOG, + DEVDIR_ENTRY_NAME)); + g_assert (devdir_entry_); + } + gtk_entry_set_text (devdir_entry_, mix_device_get_dir ()); + gtk_widget_show (devdir_dlg_); +} + +void +on_devdir_browse_clicked () +{ + GtkWidget *dialog; + const gchar *current = gtk_entry_get_text (devdir_entry_); + + dialog = + gtk_file_chooser_dialog_new (_("Devices folder"), + GTK_WINDOW (devdir_dlg_), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (current != NULL) + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), current); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + char *filename + = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + gtk_entry_set_text (devdir_entry_, filename); + g_free (filename); + } + + gtk_widget_destroy (dialog); +} + +void +on_devdir_cancel_clicked () +{ + gtk_widget_hide (devdir_dlg_); +} + +void +on_devdir_ok_clicked () +{ + const gchar *dirname = gtk_entry_get_text (devdir_entry_); + gchar *cmd = g_strconcat (mix_vm_command_to_string (MIX_CMD_SDDIR), + " ", dirname, NULL); + gtk_widget_hide (devdir_dlg_); + mixgtk_cmd_dispatcher_dispatch (cmd); + g_free (cmd); +} + + + +/* fonts */ +static GtkWidget ** +font_widgets_ (gint * n) +{ + gint no = gtk_notebook_get_n_pages (dev_nb_); + GtkWidget **w = g_new (GtkWidget *, no + 1); + gint k, j; + + for (k = 0, j = 0; k < no && j < mix_dev_INVALID; ++j) + { + struct mixgtk_device_t * dev = + (struct mixgtk_device_t *) mix_vm_get_device (vm_, j); + if (dev != NULL) w[k++] = dev->widget; + } + + g_assert (k == no); + w[k] = GTK_WIDGET (dev_nb_); + + if (n) *n = no; + + return w; +} + +void +on_devices_font_activate () +{ + gint no = 0; + GtkWidget **w = font_widgets_ (&no); + mixgtk_fontsel_query_font (MIX_FONT_DEVICES, w, no + 1); + g_free (w); +} + +void +mixgtk_device_update_fonts (void) +{ + gint k, n = 0; + GtkWidget **w = font_widgets_ (&n); + + g_assert (n >= 0); + + for (k = 0; k < n; ++k) + mixgtk_fontsel_set_font (MIX_FONT_DEVICES, w[k]); +} diff --git a/mixgtk/mixgtk_device.h b/mixgtk/mixgtk_device.h new file mode 100644 index 0000000..69859f3 --- /dev/null +++ b/mixgtk/mixgtk_device.h @@ -0,0 +1,45 @@ +/* -*-c-*- ---------------- mixgtk_device.h : + * Block devices used by mixgtk + * ------------------------------------------------------------------ + * Last change: Time-stamp: <01/03/04 23:43:59 jose> + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_DEVICE_H +#define MIXGTK_DEVICE_H + +#include +#include +#include + +/* init default devices */ +extern GtkWidget * +mixgtk_device_init (mix_vm_t *vm); + +extern void +mixgtk_device_update_fonts (void); + +/* change the output format of a device */ +extern void +mixgtk_device_set_format (mix_device_type_t dev, gboolean dec); + + +#endif /* MIXGTK_DEVICE_H */ + diff --git a/mixgtk/mixgtk_fontsel.c b/mixgtk/mixgtk_fontsel.c new file mode 100644 index 0000000..e88793b --- /dev/null +++ b/mixgtk/mixgtk_fontsel.c @@ -0,0 +1,142 @@ +/* -*-c-*- -------------- mixgtk_fontsel.c : + * Implementation of the functions declared in mixgtk_fontsel.h + * ------------------------------------------------------------------ + * $Id: mixgtk_fontsel.c,v 1.19 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include "mixgtk_widgets.h" +#include "mixgtk_config.h" +#include "mixgtk_mixvm.h" +#include "mixgtk_mixal.h" +#include "mixgtk_cmd_dispatcher.h" +#include "mixgtk_device.h" +#include "mixgtk_fontsel.h" + +static GtkFontSelectionDialog *fontsel_dialog_ = NULL; + +static const gchar *keys_[MIX_FONT_NO] = { + "MIX.font", "Prompt.font", "Log.font", "MIXAL.font", "Devices.font", + "Symbols.font", "Default.font" +}; + + +/* initialise the font selection dialog */ +static void +init_fontsel_ (void) +{ + fontsel_dialog_ = + GTK_FONT_SELECTION_DIALOG + (mixgtk_widget_factory_get_dialog (MIXGTK_FONTSEL_DIALOG)); + g_assert (fontsel_dialog_ != NULL); +} + +void +mixgtk_fontsel_set_font (mixgtk_font_t f, GtkWidget *w) +{ + const gchar *font; + PangoFontDescription *font_desc; + + if (f >= MIX_FONT_NO || w == NULL) return; + + font = mixgtk_config_get (keys_[f]); + if (!font) + { + mixgtk_config_update (keys_[f], "Monospace 10"); + font = mixgtk_config_get (keys_[f]); + g_assert (font); + } + + font_desc = pango_font_description_from_string (font); + + if (font_desc) + { + gtk_widget_modify_font (w, font_desc); + gtk_widget_queue_draw (w); + pango_font_description_free (font_desc); + } + else + mixgtk_config_remove (keys_[f]); + +} + +gboolean +mixgtk_fontsel_query_font (mixgtk_font_t f, GtkWidget **w, size_t no) +{ + gint result = GTK_RESPONSE_APPLY; + const gchar *current; + gboolean ret = FALSE; + + if (f >= MIX_FONT_NO) return FALSE; + if (!fontsel_dialog_) init_fontsel_ (); + + current = mixgtk_config_get (keys_[f]); + gtk_font_selection_dialog_set_font_name (fontsel_dialog_, + current? current : "Monospace 10"); + + while (result == GTK_RESPONSE_APPLY) + { + result = gtk_dialog_run (GTK_DIALOG (fontsel_dialog_)); + if (result != GTK_RESPONSE_CANCEL) + { + gint k; + mixgtk_config_update + (keys_[f], + gtk_font_selection_dialog_get_font_name (fontsel_dialog_)); + for (k = 0; k < no; ++k) + mixgtk_fontsel_set_font (f, w[k]); + ret = TRUE; + } + } + gtk_widget_hide (GTK_WIDGET (fontsel_dialog_)); + return ret; +} + +void +on_all_fonts_activate (void) +{ + gint result = GTK_RESPONSE_APPLY; + const gchar *current; + + if (!fontsel_dialog_) init_fontsel_ (); + + current = mixgtk_config_get (keys_[MIX_FONT_DEFAULT]); + gtk_font_selection_dialog_set_font_name (fontsel_dialog_, + current? current : "Monospace"); + + while (result == GTK_RESPONSE_APPLY) + { + result = gtk_dialog_run (GTK_DIALOG (fontsel_dialog_)); + if (result != GTK_RESPONSE_CANCEL) + { + gint k; + current = gtk_font_selection_dialog_get_font_name (fontsel_dialog_); + + for (k = 0; k < MIX_FONT_NO; ++k) + mixgtk_config_update (keys_[k], current); + + mixgtk_mixal_update_fonts (); + mixgtk_mixvm_update_fonts (); + mixgtk_device_update_fonts (); + mixgtk_cmd_dispatcher_update_fonts (); + } + } + gtk_widget_hide (GTK_WIDGET (fontsel_dialog_)); +} diff --git a/mixgtk/mixgtk_fontsel.h b/mixgtk/mixgtk_fontsel.h new file mode 100644 index 0000000..2228ed6 --- /dev/null +++ b/mixgtk/mixgtk_fontsel.h @@ -0,0 +1,51 @@ +/* -*-c-*- ---------------- mixgtk_fontsel.h : + * Functions for handling font selection. + * ------------------------------------------------------------------ + * $Id: mixgtk_fontsel.h,v 1.8 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_FONTSEL_H +#define MIXGTK_FONTSEL_H + +#include +#include "mixgtk_widgets.h" + +typedef enum { + MIX_FONT_MIXVM, + MIX_FONT_LOG, + MIX_FONT_PROMPT, + MIX_FONT_MIXAL, + MIX_FONT_DEVICES, + MIX_FONT_SYMBOLS, + MIX_FONT_DEFAULT, + MIX_FONT_NO +} mixgtk_font_t; + +/* configured fonts */ +extern void +mixgtk_fontsel_set_font (mixgtk_font_t f, GtkWidget *w); + +extern gboolean +mixgtk_fontsel_query_font (mixgtk_font_t f, GtkWidget **ws, size_t no); + + +#endif /* MIXGTK_FONTSEL_H */ + diff --git a/mixgtk/mixgtk_gen_handlers.c b/mixgtk/mixgtk_gen_handlers.c new file mode 100644 index 0000000..151feac --- /dev/null +++ b/mixgtk/mixgtk_gen_handlers.c @@ -0,0 +1,165 @@ +/* -*-c-*- -------------- mixgtk_gen_handlers.c : + * Implementation of the functions declared in mixgtk_gen_handlers.h + * ------------------------------------------------------------------ + * $Id: mixgtk_gen_handlers.c,v 1.10 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include "mixgtk_gen_handlers.h" +#include "mixgtk_cmd_dispatcher.h" +#include "mixgtk_config.h" + +/* grab a file with an externally provided callback */ +void +mixgtk_get_file (file_callback_t callback, + const gchar *title, + const gchar *pattern, + const gchar *def_file) +{ + if (callback != NULL) + { + GtkWidget *dialog; + + dialog = + gtk_file_chooser_dialog_new (title, + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (pattern != NULL) + { + GtkFileFilter *filter = gtk_file_filter_new (); + gtk_file_filter_add_pattern (filter, pattern); + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); + } + + if (def_file != NULL) + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), def_file); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + char *filename; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + callback (filename); + g_free (filename); + } + + gtk_widget_destroy (dialog); + } +} + +/* exec prompt command */ +static void +exec_cmd_ (mix_vm_command_t cmd, const gchar *arg) +{ + gchar *command; + if (arg) + command = g_strdup_printf ("%s %s", + mix_vm_command_to_string (cmd), + arg); + else + command = g_strdup (mix_vm_command_to_string (cmd)); + mixgtk_cmd_dispatcher_dispatch (command); + g_free (command); +} + +/* load mix binary */ +static void +open_cb_ (const gchar *file) +{ + if (file) + exec_cmd_ (MIX_CMD_LOAD, file); +} + +void +on_file_open_activate (GtkWidget *w, gpointer data) +{ + mixgtk_get_file (open_cb_, _("Load MIX program..."), "*.mix", NULL); +} + +/* edit mixal source */ +static void +edit_cb_ (const gchar *file) +{ + exec_cmd_ (MIX_CMD_EDIT, file); +} + +void +on_file_edit_activate (GtkWidget *w, gpointer data) +{ + mixgtk_get_file (edit_cb_, _("Edit MIXAL source file..."), "*.mixal", + mixgtk_cmd_dispatcher_get_src_path ()); +} + +/* compile mixal source */ +static void +compile_cb_ (const gchar *file) +{ + exec_cmd_ (MIX_CMD_COMPILE, file); +} + +void +on_file_compile_activate (GtkWidget *w, gpointer data) +{ + mixgtk_get_file (compile_cb_, _("Compile MIXAL source file..."), "*.mixal", + mixgtk_cmd_dispatcher_get_src_path ()); +} + +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)); +} + +void +on_save_on_exit_toggle (GtkWidget *w, gpointer data) +{ + mixgtk_config_set_autosave (GTK_CHECK_MENU_ITEM (w)->active); +} + +void +on_save_activate (GtkWidget *w, gpointer data) +{ + mixgtk_config_save (); +} + + diff --git a/mixgtk/mixgtk_gen_handlers.h b/mixgtk/mixgtk_gen_handlers.h new file mode 100644 index 0000000..c82c195 --- /dev/null +++ b/mixgtk/mixgtk_gen_handlers.h @@ -0,0 +1,62 @@ +/* -*-c-*- ---------------- mixgtk_gen_handlers.h : + * general signal handlers declarations + * ------------------------------------------------------------------ + * $Id: mixgtk_gen_handlers.h,v 1.7 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_GEN_HANDLERS_H +#define MIXGTK_GEN_HANDLERS_H + +#include + +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_file_edit_activate (GtkWidget *w, gpointer data); + +extern void +on_file_compile_activate (GtkWidget *w, gpointer data); + +extern void +on_clear_breakpoints_activate (GtkWidget *w, gpointer data); + +extern void +on_save_on_exit_toggle (GtkWidget *w, gpointer data); + +extern void +on_save_activate (GtkWidget *w, gpointer data); + +typedef void (*file_callback_t)(const gchar *file); + +extern void +mixgtk_get_file (file_callback_t callback, const gchar *title, + const gchar *pattern, const gchar *def_file); + + +#endif /* MIXGTK_GEN_HANDLERS_H */ + diff --git a/mixgtk/mixgtk_input.c b/mixgtk/mixgtk_input.c new file mode 100644 index 0000000..238fadd --- /dev/null +++ b/mixgtk/mixgtk_input.c @@ -0,0 +1,233 @@ +/* -*-c-*- -------------- mixgtk_input.c : + * Implementation of the functions declared in mixgtk_input.h + * ------------------------------------------------------------------ + * $Id: mixgtk_input.c,v 1.7 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#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_ = NULL; +static GtkWidget *childs_[SIZE_]; +static input_callback_t callback_; +static gpointer data_; + + +static void init_dialog_ (void); +static void set_word_ (mix_word_t word); + + +/* init */ +void +mixgtk_input_init (void) +{ + dialog_ = NULL; +} + +/* get a word */ +void +mixgtk_input_word (const gchar *message, mix_word_t def, + input_callback_t cb, gpointer data) +{ + if (!dialog_) init_dialog_ (); + 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) +{ + if (!dialog_) init_dialog_ (); + 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 + +/* dec and bytes input handler */ +void +on_word_dec_changed (GtkEditable *dec, gpointer *data) +{ + gchar *txt = gtk_editable_get_chars (dec, 0, -1); + + if (strlen (txt) > 0) + { + gint val = atoi (txt); + set_word_ (mix_word_new (val)); + } + g_free (txt); +} + +void +on_word_byte_changed (GtkEditable *byte, gpointer *data) +{ + gchar *txt = gtk_editable_get_chars (byte, 0, 2); + + if (strlen (txt) > 0) + { + mix_byte_t bytes[5]; + gint k; + const gchar *s; + mix_word_t w; + + for (k = 0; k < 5; ++k) + { + const 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); + } + g_free (txt); +} + +void +on_word_sign_changed (GtkEditable *sign, gpointer *data) +{ + gchar *txt = gtk_editable_get_chars (sign, 0, 1); + + if (strlen (txt) > 0) + { + gint pos = 0; + mix_word_t w = + mix_word_new (atoi (gtk_entry_get_text (GTK_ENTRY (childs_[DEC_])))); + + g_signal_handlers_block_by_func (GTK_OBJECT (sign), + on_word_sign_changed, data); + + if (txt[0] != '+' && txt[0] != '-') txt[0] = '+'; + gtk_editable_delete_text (sign, 0, 1); + gtk_editable_insert_text (sign, txt, 1, &pos); + + g_signal_handlers_unblock_by_func (GTK_OBJECT (sign), + on_word_sign_changed, data); + set_word_ (txt[0] == '-' ? mix_word_negative (w) : w); + } + g_free (txt); +} + +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)); + if (w == MIX_WORD_ZERO) + { + const gchar *sign = gtk_entry_get_text (GTK_ENTRY (childs_[SIGN_])); + if (sign && sign[0] == '-') mix_word_reverse_sign (w); + } + 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); +} + +static void +init_dialog_ (void) +{ + gint k; + + dialog_ = GTK_DIALOG (mixgtk_widget_factory_get_dialog (MIXGTK_WORD_DIALOG)); + g_assert (dialog_ != NULL); + for (k = 0; k < SIZE_; ++k) + { + childs_[k] = mixgtk_widget_factory_get_child_by_name + (MIXGTK_WORD_DIALOG, WGT_NAMES_[k]); + g_assert (childs_[k] != NULL); + } +} + +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); + g_snprintf (BUFFER, SIZE, "%s%d", neg ? "-" : "", val); + + + g_signal_handlers_block_by_func (GTK_OBJECT (childs_[DEC_]), + on_word_dec_changed, NULL); + g_signal_handlers_block_by_func (GTK_OBJECT (childs_[SIGN_]), + on_word_sign_changed, NULL); + for (k = B1_; k <= B5_; ++k) + g_signal_handlers_block_by_func (GTK_OBJECT (childs_[k]), + on_word_byte_changed, NULL); + + 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); + g_snprintf (BUFFER, SIZE, "%d", (int)b); + gtk_entry_set_text (GTK_ENTRY (childs_[SIGN_ + k]), BUFFER); + } + + for (k = B1_; k <= B5_; ++k) + g_signal_handlers_unblock_by_func (GTK_OBJECT (childs_[k]), + on_word_byte_changed, NULL); + g_signal_handlers_unblock_by_func (GTK_OBJECT (childs_[DEC_]), + on_word_dec_changed, NULL); + g_signal_handlers_unblock_by_func (GTK_OBJECT (childs_[SIGN_]), + on_word_sign_changed, NULL); +} + diff --git a/mixgtk/mixgtk_input.h b/mixgtk/mixgtk_input.h new file mode 100644 index 0000000..924e90b --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_INPUT_H +#define MIXGTK_INPUT_H + +#include + +/* callback function type */ +typedef void (*input_callback_t)(mix_word_t result, gpointer data); + +/* init */ +extern void +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..50d09a7 --- /dev/null +++ b/mixgtk/mixgtk_mixal.c @@ -0,0 +1,580 @@ +/* -*-c-*- -------------- mixgtk_mixal.c : + * Implementation of the functions declared in mixgtk_mixal.h + * ------------------------------------------------------------------ + * $Id: mixgtk_mixal.c,v 1.22 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include + +#include "mixgtk_widgets.h" +#include "mixgtk_config.h" +#include "mixgtk_fontsel.h" +#include "mixgtk_mixal.h" + +static mix_vm_t *vm_ = NULL; +static GtkTreeView *clist_ = NULL; +static GtkListStore *clist_store_ = NULL; + +static gulong lineno_; +static GtkStatusbar *status_ = NULL; +static gint status_context_ = 0; +static GPtrArray *tips_text_ = NULL; + +static GtkWidget *symbols_dlg_ = NULL; +static GtkTreeView *symbols_view_ = NULL; +static GtkListStore *symbols_store_ = NULL; +static const gchar *SYMBOLS_VIEW_NAME_ = "symbols_view"; + +static const gchar *bp_stock_id_ = NULL; +static const gchar *pc_stock_id_ = NULL; +static const guint bp_stock_size_ = GTK_ICON_SIZE_MENU; + +enum { + CLIST_BP_ID_COL, + CLIST_BP_SIZE_COL, + CLIST_ADDRESS_COL, + CLIST_BYTECODE_COL, + CLIST_CODE_COL, + CLIST_ADDRESS_NO_COL, + CLIST_LINE_NO_COL, + CLIST_COL_NO +}; + +enum { + SYMBOLS_NAME_COL, + SYMBOLS_VALUE_COL, + SYMBOLS_WORD_COL, + SYMBOLS_COL_NO +}; + + +static gboolean +mixal_event_ (GtkWidget *w, GdkEvent *event, gpointer data); + + +static void +init_symbols_ (void) +{ + GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); + + symbols_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_SYMBOLS_DIALOG); + g_assert (symbols_dlg_); + symbols_view_ = GTK_TREE_VIEW + (mixgtk_widget_factory_get_child_by_name + (MIXGTK_SYMBOLS_DIALOG, SYMBOLS_VIEW_NAME_)); + g_assert (symbols_view_); + + mixgtk_fontsel_set_font (MIX_FONT_SYMBOLS, GTK_WIDGET (symbols_view_)); + + symbols_store_ = gtk_list_store_new (SYMBOLS_COL_NO, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (symbols_store_), + SYMBOLS_NAME_COL, + GTK_SORT_ASCENDING); + + gtk_tree_view_set_model (symbols_view_, GTK_TREE_MODEL (symbols_store_)); + g_object_unref (G_OBJECT (symbols_store_)); + gtk_tree_view_append_column + (symbols_view_, + gtk_tree_view_column_new_with_attributes ("Name", renderer, + "text", SYMBOLS_NAME_COL, + NULL)); + gtk_tree_view_append_column + (symbols_view_, + gtk_tree_view_column_new_with_attributes ("Value", renderer, + "text", SYMBOLS_VALUE_COL, + NULL)); + gtk_tree_view_append_column + (symbols_view_, + gtk_tree_view_column_new_with_attributes ("", renderer, + "text", SYMBOLS_WORD_COL, + NULL)); +} + +static void +insert_symbol_ (gpointer symbol, gpointer value, gpointer data) +{ + enum {DEC_SIZE = 25, WORD_SIZE = 20}; + static gchar DEC[DEC_SIZE], WORD[WORD_SIZE]; + + GtkTreeIter iter; + + mix_word_t w = (mix_word_t)GPOINTER_TO_INT (value); + g_snprintf (DEC, DEC_SIZE, "%s%ld", + mix_word_is_negative (w)? "-" : "+", + mix_word_magnitude (w)); + mix_word_print_to_buffer (w, WORD); + + gtk_list_store_append (symbols_store_, &iter); + gtk_list_store_set (symbols_store_, &iter, + SYMBOLS_NAME_COL, (const gchar*)symbol, + SYMBOLS_VALUE_COL, DEC, + SYMBOLS_WORD_COL, WORD, + -1); +} + +static void +fill_symbols_ (const mix_symbol_table_t *table) +{ + if (symbols_view_) + gtk_list_store_clear (symbols_store_); + else + init_symbols_ (); + + mix_symbol_table_foreach (((mix_symbol_table_t *)table), + insert_symbol_, NULL); +} + +static void +init_clist_ (void) +{ + GtkStockItem item; + + GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); + GtkCellRenderer *bprenderer = gtk_cell_renderer_pixbuf_new (); + + clist_ = GTK_TREE_VIEW (gtk_tree_view_new ()); + + clist_store_ = gtk_list_store_new (CLIST_COL_NO, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_INT); + + gtk_tree_view_set_model (clist_, GTK_TREE_MODEL (clist_store_)); + g_object_unref (G_OBJECT (clist_store_)); + gtk_tree_view_set_rules_hint (clist_, TRUE); + + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("", bprenderer, + "stock-id", CLIST_BP_ID_COL, + "stock-size", CLIST_BP_SIZE_COL, + NULL)); + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("Address", renderer, + "text", CLIST_ADDRESS_COL, + NULL)); + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("Bytecode", renderer, + "text", CLIST_BYTECODE_COL, + NULL)); + gtk_tree_view_append_column + (clist_, + gtk_tree_view_column_new_with_attributes ("Source", renderer, + "text", CLIST_CODE_COL, + NULL)); + + if (gtk_stock_lookup (GTK_STOCK_STOP, &item)) + { + bp_stock_id_ = item.stock_id; + } + + if (gtk_stock_lookup (GTK_STOCK_GO_FORWARD, &item)) + { + pc_stock_id_ = item.stock_id; + } + + symbols_dlg_ = NULL; + symbols_view_ = NULL; + + g_signal_connect (G_OBJECT (clist_), "event", + G_CALLBACK (mixal_event_), NULL); + + + mixgtk_fontsel_set_font (MIX_FONT_MIXAL, GTK_WIDGET (clist_)); + + gtk_widget_show (GTK_WIDGET (clist_)); + +} + + +/* initialise the mixal widgets */ +GtkWidget * +mixgtk_mixal_init (mix_vm_t *vm) +{ + if (vm != NULL) vm_ = vm; + + if (vm_ == NULL) return FALSE; + + if (clist_ == NULL) init_clist_ (); + + status_ = NULL; + + return GTK_WIDGET (clist_); +} + +void +mixgtk_mixal_reparent (GtkStatusbar *status) +{ + g_assert (status != NULL); + mixgtk_mixal_pop_status (); + status_ = status; + status_context_ = gtk_statusbar_get_context_id (status_, "MIXAL status"); +} + +void +mixgtk_mixal_update_fonts (void) +{ + mixgtk_fontsel_set_font (MIX_FONT_MIXAL, GTK_WIDGET (clist_)); + mixgtk_fontsel_set_font (MIX_FONT_SYMBOLS, GTK_WIDGET (symbols_view_)); +} + +void +mixgtk_mixal_pop_status (void) +{ + if (status_ != NULL) + gtk_statusbar_pop (status_, status_context_); +} + +/* load the corresponding mixal file */ +static void +update_tips_ (const mix_symbol_table_t *table, + const gchar *line) +{ + enum {SIZE = 256}; + static gchar BUFFER[256]; + static const gchar *DELIMITERS = " /+*=-()\t,:\n"; + if (line) + { + guint k = 0; + gchar *tip = g_strdup (""); + gchar *new_tip; + gchar **tokens; + gchar *text = g_strdup (line); + text = g_strdelimit (text, DELIMITERS, ' '); + tokens = g_strsplit (g_strstrip (text), " ", -1); + while (tokens[k]) + { + if (mix_symbol_table_is_defined (table, tokens[k])) + { + mix_word_t val = mix_symbol_table_value (table, tokens[k]); + g_snprintf (BUFFER, SIZE, "[ %s = %s%ld ]", tokens[k], + mix_word_is_negative (val)? "-" : "+", + mix_word_magnitude (val)); + new_tip = g_strconcat (tip, " ", BUFFER, NULL); + g_free (tip); + tip = new_tip; + } + ++k; + } + g_ptr_array_add (tips_text_, (gpointer)tip); + g_strfreev (tokens); + g_free (text); + } +} + +void +mixgtk_mixal_load_file (void) +{ + enum {ADDR_SIZE = 20, CONT_SIZE = 200, WORD_SIZE = 20}; + static gchar ADDR[ADDR_SIZE], CONT[CONT_SIZE], WORD[WORD_SIZE]; + + const mix_src_file_t *file; + GtkTreeIter iter; + + g_assert (vm_); + g_assert (clist_); + + gtk_list_store_clear (clist_store_); + if (tips_text_) + { + g_ptr_array_free (tips_text_, TRUE); + tips_text_ = NULL; + } + + file = mix_vm_get_src_file (vm_); + if (file != NULL) + { + gint k; + + mix_address_t addr; + const mix_symbol_table_t *table = mix_vm_get_symbol_table (vm_); + + if (table) tips_text_ = g_ptr_array_new (); + + lineno_ = mix_src_file_get_line_no (file); + + for (k = 0; k < lineno_; ++k) + { + gchar *line = + g_strchomp ((gchar *)mix_src_file_get_line (file, k + 1)); + + g_snprintf (CONT, CONT_SIZE, " %03d: %s", k + 1, line); + addr = mix_vm_get_lineno_address (vm_, k + 1); + if (addr != MIX_VM_CELL_NO) + { + g_snprintf (ADDR, ADDR_SIZE, "%04d", mix_short_magnitude (addr)); + mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, addr), + WORD); + } + else + { + g_snprintf (ADDR, ADDR_SIZE, _("N/A")); + g_snprintf (WORD, WORD_SIZE, _("N/A")); + } + gtk_list_store_append (clist_store_, &iter); + gtk_list_store_set (clist_store_, &iter, + CLIST_ADDRESS_NO_COL, mix_short_magnitude (addr), + CLIST_LINE_NO_COL, k + 1, + CLIST_ADDRESS_COL, ADDR, + CLIST_CODE_COL, CONT, + CLIST_BYTECODE_COL, WORD, + CLIST_BP_SIZE_COL, bp_stock_size_, + -1); + if (table) update_tips_ (table, line); + } + if (table) fill_symbols_ (table); + } + else + { + lineno_ = 0; + gtk_list_store_append (clist_store_, &iter); + gtk_list_store_set (clist_store_, &iter, + CLIST_ADDRESS_NO_COL, MIX_VM_CELL_NO, + CLIST_LINE_NO_COL, 0, + CLIST_ADDRESS_COL, "", + CLIST_CODE_COL, _("Source not available"), + CLIST_BYTECODE_COL, "", + -1); + } +} + + +/* update the widgets */ +static gint +find_address_ (gint address) +{ + GtkTreeIter iter; + gint addr; + gint row = 0; + gboolean valid = + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (clist_store_), &iter); + + while (valid) + { + ++row; + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), &iter, + CLIST_ADDRESS_NO_COL, &addr, -1); + if (addr == address) return row; + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (clist_store_), &iter); + } + return 0; +} + +static void +update_bp_ (gint row) +{ + if (row > 0) + { + GtkTreePath *path = gtk_tree_path_new_from_indices (row - 1, -1); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), &iter, path)) + { + gint address; + const gchar *id = NULL; + + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), &iter, + CLIST_ADDRESS_NO_COL, &address, -1); + if (mix_vm_has_breakpoint_at_address (vm_, address)) + id = bp_stock_id_; + else if (address == + (gint) mix_short_magnitude (mix_vm_get_prog_count (vm_))) + id = pc_stock_id_; + + gtk_list_store_set (clist_store_, &iter, CLIST_BP_ID_COL, id, -1); + } + gtk_tree_path_free (path); + } +} + +static void +select_row_ (gint row) +{ + static gint previous = 0; + + if (row > 0 && previous != row) + { + GtkTreePath *path = gtk_tree_path_new_from_indices (row - 1, -1); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), &iter, path)) + { + gtk_list_store_set (clist_store_, &iter, + CLIST_BP_ID_COL, pc_stock_id_, + -1); + update_bp_ (previous); + previous = row; + gtk_tree_view_scroll_to_cell (clist_, path, NULL, FALSE, 0.3, 0); + } + gtk_tree_path_free (path); + } +} + +void +mixgtk_mixal_update (void) +{ + gint addr = 0; + + g_assert (vm_); + + addr = (gint) mix_short_magnitude (mix_vm_get_prog_count (vm_)); + select_row_ (find_address_ (addr)); +} + +/* breakpoints */ +void +mixgtk_mixal_update_bp_at_address (guint addr) +{ + update_bp_ (find_address_ ((gint)addr)); +} + +void +mixgtk_mixal_update_bp_at_line (guint line) +{ + update_bp_ ((gint)line); +} + +void +mixgtk_mixal_update_bp_all (void) +{ + gint k; + for (k = 1; k <= lineno_; ++k) update_bp_ (k); + mixgtk_mixal_update (); +} + +/* callbacks */ +static void +mixal_row_clicked_ (GtkTreeIter *iter) +{ + + gint addr = MIX_VM_CELL_NO; + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), + iter, CLIST_ADDRESS_NO_COL, &addr, -1); + + if (addr < MIX_VM_CELL_NO) + { + gboolean 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); + update_bp_ (find_address_ (addr)); + } +} + +static void +mixal_motion_ (GtkTreeIter *iter) +{ + static gint last_row = 0; + static guint last_message = 0; + + gint row = last_row; + + gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), iter, + CLIST_LINE_NO_COL, &row, -1); + + if (row > 0 && row != last_row && tips_text_) + { + const gchar *msg = NULL; + last_row = row; + if (last_message) + gtk_statusbar_remove (status_, status_context_, last_message); + msg = (const gchar *)g_ptr_array_index (tips_text_, row - 1); + if (msg) + last_message = gtk_statusbar_push (status_, status_context_, msg); + else + last_message = 0; + } +} + +static gboolean +mixal_event_ (GtkWidget *w, GdkEvent *event, gpointer data) +{ + GdkEventType type = event->type; + if ((type == GDK_BUTTON_PRESS || type == GDK_MOTION_NOTIFY) + && (gtk_tree_view_get_bin_window (clist_) == event->any.window)) + { + gdouble x = (type == GDK_BUTTON_PRESS)? event->button.x : event->motion.x; + gdouble y = (type == GDK_BUTTON_PRESS)? event->button.y : event->motion.y; + GtkTreeIter iter; + GtkTreePath *path = NULL; + GtkTreeViewColumn *col = NULL; + if (gtk_tree_view_get_path_at_pos (clist_, x, y, &path, &col, NULL, NULL) + && gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), + &iter, path)) + { + if (type == GDK_BUTTON_PRESS) mixal_row_clicked_ (&iter); + else mixal_motion_ (&iter); + } + if (path) gtk_tree_path_free (path); + return TRUE; + } + return FALSE; +} + +void +on_symbol_ok_clicked () +{ + gtk_widget_hide (symbols_dlg_); +} + +void +on_symbols_activate () +{ + if (!symbols_dlg_) init_symbols_ (); + gtk_widget_show (symbols_dlg_); +} + +void +on_mixal_leave_notify_event () +{ + if (status_ != NULL) gtk_statusbar_pop (status_, status_context_); +} + +void +on_mixal_font_activate () +{ + GtkWidget *w[] = { GTK_WIDGET (clist_) }; + mixgtk_fontsel_query_font (MIX_FONT_MIXAL, w, 1); +} + +void +on_symbols_font_activate () +{ + if (symbols_view_ != NULL) + { + GtkWidget *w[] = { GTK_WIDGET (symbols_view_) }; + mixgtk_fontsel_query_font (MIX_FONT_SYMBOLS, w, 1); + } + else + mixgtk_fontsel_query_font (MIX_FONT_SYMBOLS, NULL, 0); +} diff --git a/mixgtk/mixgtk_mixal.h b/mixgtk/mixgtk_mixal.h new file mode 100644 index 0000000..1afe9a0 --- /dev/null +++ b/mixgtk/mixgtk_mixal.h @@ -0,0 +1,66 @@ +/* -*-c-*- ---------------- mixgtk_mixal.h : + * Declarations for functions displaying the mixal source file + * ------------------------------------------------------------------ + * $Id: mixgtk_mixal.h,v 1.8 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_MIXAL_H +#define MIXGTK_MIXAL_H + +#include +#include +#include "mixgtk_widgets.h" + + +/* initialise the mixal widget */ +extern GtkWidget * +mixgtk_mixal_init (mix_vm_t *vm); + +extern void +mixgtk_mixal_reparent (GtkStatusbar *stat); + +/* load the corresponding mixal file */ +extern void +mixgtk_mixal_load_file (void); + +/* update the widget */ +extern void +mixgtk_mixal_update (void); + +extern void +mixgtk_mixal_update_fonts (void); + +extern void +mixgtk_mixal_pop_status (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); + + +#endif /* MIXGTK_MIXAL_H */ + diff --git a/mixgtk/mixgtk_mixvm.c b/mixgtk/mixgtk_mixvm.c new file mode 100644 index 0000000..cc74e27 --- /dev/null +++ b/mixgtk/mixgtk_mixvm.c @@ -0,0 +1,529 @@ +/* -*-c-*- -------------- mixgtk_mixvm.c : + * Implementation of the functions declared in mixgtk_mixvm.h + * ------------------------------------------------------------------ + * $Id: mixgtk_mixvm.c,v 1.16 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include "mixgtk_widgets.h" +#include "mixgtk_fontsel.h" +#include "mixgtk_mixvm.h" +#include "mixgtk_cmd_dispatcher.h" +#include "mixgtk_input.h" + + +/* Local variables */ + +#define REGISTER_NO_ (MIXGTK_WIDGET_rI6 - MIXGTK_WIDGET_rA + 1) + +static GtkEntry *reg_entries_[REGISTER_NO_]; +static GtkTooltips *tips_ = NULL; +static GtkEntry *loc_entry_; +static GtkWidget *goto_ = NULL; +static GtkEntry *goto_entry_ = NULL; +static GtkToggleButton *over_button_; +static GtkToggleButton *cmp_buttons_[3]; +static GtkTreeView *memory_; +static GtkListStore *mem_store_; +static GtkLabel *laptime_; +static GtkLabel *progtime_; +static GtkLabel *uptime_; +static mix_vm_t *vm_; + + +/* Static function prototypes */ +static void init_goto_ (void); +static void update_register_ (mixgtk_widget_id_t reg); +static gboolean init_mem_ (void); + + +enum { + MEM_ADDRESS_COL, + MEM_CONTENTS_COL, + MEM_COL_NO +}; + + +/* initialise the mixvm widgets */ +gboolean +mixgtk_mixvm_init (mix_vm_t *vm) +{ + int k; + + g_assert (vm != NULL); + + vm_ = vm; + + if (!tips_) tips_ = gtk_tooltips_new (); + + for (k = 0; k < REGISTER_NO_; ++k) + { + reg_entries_[k] = + GTK_ENTRY (mixgtk_widget_factory_get(MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_rA + k)); + g_assert (reg_entries_[k] != NULL); + mixgtk_fontsel_set_font (MIX_FONT_MIXVM, + GTK_WIDGET (reg_entries_[k])); + } + + loc_entry_ = + GTK_ENTRY (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_LOC)); + g_assert (loc_entry_ != NULL); + mixgtk_fontsel_set_font (MIX_FONT_MIXVM, GTK_WIDGET (loc_entry_)); + + uptime_ = + GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_UPTIME)); + g_assert (uptime_ != NULL); + + progtime_ = + GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_PROGTIME)); + g_assert (progtime_ != NULL); + + laptime_ = + GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_LAPTIME)); + g_assert (laptime_ != NULL); + + over_button_ = + GTK_TOGGLE_BUTTON + (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, MIXGTK_WIDGET_OVER)); + g_assert (over_button_ != NULL); + + for (k = 0; k < 3; ++k) + { + cmp_buttons_[k] = GTK_TOGGLE_BUTTON + (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_CMP_L +k)); + g_assert (cmp_buttons_[k] != NULL); + } + init_mem_ (); + + return TRUE; +} + +static GtkWidget ** +text_widgets_ (gint *n) +{ + static GtkWidget *w[REGISTER_NO_ + 2] = { NULL}; + + if (w[0] == NULL) + { + gint k; + w[0] = GTK_WIDGET (loc_entry_); + w[1] = GTK_WIDGET (memory_); + for (k = 0; k < REGISTER_NO_; ++k) + w[k + 2] = GTK_WIDGET (reg_entries_[k]); + }; + + if (n) *n = REGISTER_NO_ + 2; + + return w; +} + +void +mixgtk_mixvm_update_fonts (void) +{ + gint k, n = 0; + GtkWidget **w = text_widgets_ (&n); + for (k = 0; k < n; ++k) + mixgtk_fontsel_set_font (MIX_FONT_MIXVM, w[k]); +} + +/* 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]; + GtkTreeIter iter; + gboolean valid = + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (mem_store_), &iter); + gint k = 0; + + while (valid) + { + mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, k++), BUFFER); + gtk_list_store_set (mem_store_, &iter, MEM_CONTENTS_COL, BUFFER, -1); + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (mem_store_), &iter); + } +} + +void +mixgtk_mixvm_update_cells_to_address (gint address) +{ + GtkTreePath *path = gtk_tree_path_new_from_indices (address, -1); + + if (address >= MIX_VM_CELL_NO) return; + gtk_tree_view_scroll_to_cell (memory_, path, NULL, TRUE, 0, 0); + gtk_tree_path_free (path); +} + +/* 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_); + g_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); + g_snprintf (BUFFER, SIZE, "%d", uptime); + gtk_label_set_text (uptime_, BUFFER); + g_snprintf (BUFFER, SIZE, "%d", progtime); + gtk_label_set_text (progtime_, BUFFER); + g_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])) + { + g_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 TRUE; +} + +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_mix_font_activate (void) +{ + gint n; + GtkWidget **w = text_widgets_ (&n); + mixgtk_fontsel_query_font (MIX_FONT_MIXVM, w, n); +} + + + +/* static functions */ +static void +init_goto_ (void) +{ + goto_ = mixgtk_widget_factory_get_dialog (MIXGTK_GOTO_DIALOG); + g_assert (goto_ != NULL); + goto_entry_ = + GTK_ENTRY (mixgtk_widget_factory_get (MIXGTK_GOTO_DIALOG, + MIXGTK_WIDGET_GOTO_ENTRY)); + g_assert (goto_entry_ != NULL); +} + +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); + g_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 +cells_clicked_ (GtkTreeViewColumn* col, gpointer data) +{ + if (!goto_) init_goto_ (); + if (gtk_dialog_run (GTK_DIALOG (goto_)) == GTK_RESPONSE_OK) + { + const gchar *txt = gtk_entry_get_text (goto_entry_); + mix_short_t addr = mix_short_new (atoi (txt)); + if (addr < MIX_VM_CELL_NO) + mixgtk_mixvm_update_cells_to_address (addr); + } + gtk_widget_hide (goto_); +} + +static gboolean +cont_clicked_ (GtkWidget *w, GdkEvent *event, gpointer data) +{ + enum {SIZE = 30}; + static gchar BUFFER[SIZE]; + + if (event->type == GDK_BUTTON_PRESS) + { + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (memory_)); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + gint addr; + + gtk_tree_model_get (model, &iter, MEM_ADDRESS_COL, &addr, -1); + g_snprintf (BUFFER, SIZE, _("Memory cell no. %d"), addr); + mixgtk_input_word + (BUFFER, + mix_vm_get_addr_contents (vm_, mix_short_new (addr)), + mem_cell_, GINT_TO_POINTER (addr)); + } + } + + return FALSE; +} + + +static gboolean +init_mem_ (void) +{ + gint k; + GtkTreeIter iter; + GtkCellRenderer *renderer; + GtkTreeViewColumn *col; + + /* model */ + + mem_store_ = gtk_list_store_new (MEM_COL_NO, G_TYPE_INT, G_TYPE_STRING); + + g_assert (mem_store_); + + for (k = 0; k< MIX_VM_CELL_NO; ++k) + { + gtk_list_store_append (mem_store_, &iter); + gtk_list_store_set (mem_store_, &iter, + MEM_ADDRESS_COL, k, + MEM_CONTENTS_COL, "+ 00 00 00 00 00", + -1); + } + + /* view */ + + renderer = gtk_cell_renderer_text_new (); + memory_ = + GTK_TREE_VIEW (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_CELLS)); + + g_assert (memory_); + g_assert (renderer); + + gtk_tree_view_set_model (memory_, GTK_TREE_MODEL (mem_store_)); + gtk_tree_view_set_headers_clickable (memory_, TRUE); + g_object_unref (G_OBJECT (mem_store_)); + + col = gtk_tree_view_column_new_with_attributes ("Address", renderer, + "text", 0, NULL); + gtk_tree_view_column_set_clickable (col, TRUE); + g_signal_connect (G_OBJECT (col), "clicked", + G_CALLBACK (cells_clicked_), NULL); + + gtk_tree_view_append_column (memory_, col); + + + col = gtk_tree_view_column_new_with_attributes ("Contents", renderer, + "text", 1, NULL); + gtk_tree_view_column_set_clickable (col, TRUE); + g_signal_connect (G_OBJECT (col), "clicked", + G_CALLBACK (cont_clicked_), NULL); + + gtk_tree_view_append_column (memory_, col); + + g_signal_connect (G_OBJECT (memory_), "event-after", + G_CALLBACK (cont_clicked_), NULL); + + mixgtk_fontsel_set_font (MIX_FONT_MIXVM, GTK_WIDGET (memory_)); + + return TRUE; +} + diff --git a/mixgtk/mixgtk_mixvm.h b/mixgtk/mixgtk_mixvm.h new file mode 100644 index 0000000..79a8d72 --- /dev/null +++ b/mixgtk/mixgtk_mixvm.h @@ -0,0 +1,72 @@ +/* -*-c-*- ---------------- mixgtk_mixvm.h : + * Functions dealing with the mixvm widgets + * ------------------------------------------------------------------ + * $Id: mixgtk_mixvm.h,v 1.6 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_MIXVM_H +#define MIXGTK_MIXVM_H + +#include +#include "mixgtk.h" +#include "mixgtk_widgets.h" + +/* initialise the mixvm widgets */ +extern gboolean +mixgtk_mixvm_init (mix_vm_t *vm); + +extern void +mixgtk_mixvm_update_fonts (void); + +/* 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); + + +#endif /* MIXGTK_MIXVM_H */ + diff --git a/mixgtk/mixgtk_widgets.c b/mixgtk/mixgtk_widgets.c new file mode 100644 index 0000000..724b578 --- /dev/null +++ b/mixgtk/mixgtk_widgets.c @@ -0,0 +1,153 @@ +/* -*-c-*- -------------- mixgtk_widgets.c : + * Implementation of the functions declared in mixgtk_widgets.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "2001-04-29 14:32:17 jao" + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include +#include "mixgtk_config.h" +#include "mixgtk_widgets.h" + +/* dialog names */ +static const gchar * dnames_[] = { + "main_window", + "mixvm_window", + "mixal_window", + "devices_window", + "word_dialog", + "about_dialog", + "goto_dialog", + "fontsel_dialog", + "devform_dialog", + "external_dialog", + "symbols_dialog", + "input_dialog", + "devdir_dialog" +}; + +#define DLG_NO_ (sizeof (dnames_) / sizeof(dnames_[0])) + +/* widget names */ +static const gchar *names_[] = { + "main_statusbar", + "attach_button", + "main_notebook", + "mixvm_widget", + "mixvm_container", + "command_prompt", + "command_log", + "dev_container", + "mixal_container", + "mixal_statusbar", + "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", + "elapsed_label", + "program_label", + "uptime_label", + "devices_container", + "loc_entry", + "goto_entry", + NULL +}; + +#define WIDGET_NO_ (sizeof (names_) / sizeof (names_[0])) + +/* the glade specs */ +static GladeXML *xml_[DLG_NO_] = {NULL}; + +/* the xml file name */ +static const gchar *file_ = NULL; + +static void init_xml_ (mixgtk_dialog_id_t dlg) +{ + xml_[dlg] = glade_xml_new (file_, dnames_[dlg], NULL); + glade_xml_signal_autoconnect (xml_[dlg]); + g_assert (xml_[dlg] != NULL); +} + +/* create a new factory from an xml glade file */ +gboolean +mixgtk_widget_factory_init (void) +{ + if (!file_) + { + const gchar *glade_file = GLADE_FILE; + glade_init (); + if (access (glade_file, R_OK)) { + if (access (LOCAL_GLADE_FILE, R_OK)) return FALSE; + glade_file = LOCAL_GLADE_FILE; + } + file_ = g_strdup (glade_file); + } + else + { + gint k; + for (k = 0; k < DLG_NO_; ++k) if (xml_[k]) xml_[k] = NULL; + } + + init_xml_ (MIXGTK_MAIN); + return TRUE; +} + +/* get a widget */ +GtkWidget * +mixgtk_widget_factory_get (mixgtk_dialog_id_t dlg, mixgtk_widget_id_t widget) +{ + g_assert (widget < WIDGET_NO_); + + return mixgtk_widget_factory_get_child_by_name (dlg, names_[widget]); +} + + +GtkWidget * +mixgtk_widget_factory_get_dialog (mixgtk_dialog_id_t dlg) +{ + g_assert (dlg < DLG_NO_); + + if (!xml_[dlg]) init_xml_ (dlg); + return glade_xml_get_widget (xml_[dlg], dnames_[dlg]); +} + +GtkWidget * +mixgtk_widget_factory_get_child_by_name (mixgtk_dialog_id_t dlg, + const gchar *name) +{ + g_assert (dlg < DLG_NO_); + g_assert (name != NULL); + if (!xml_[dlg]) init_xml_ (dlg); + return glade_xml_get_widget (xml_[dlg], name); +} + + diff --git a/mixgtk/mixgtk_widgets.h b/mixgtk/mixgtk_widgets.h new file mode 100644 index 0000000..720f962 --- /dev/null +++ b/mixgtk/mixgtk_widgets.h @@ -0,0 +1,102 @@ +/* -*-c-*- ---------------- mixgtk_widgets.h : + * glade-based factory of mixvm widgets + * ------------------------------------------------------------------ + * $Id: mixgtk_widgets.h,v 1.15 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_WIDGETS_H +#define MIXGTK_WIDGETS_H + +#include +#include + +/* enumeration of gmixvm dialogs */ +typedef enum { + MIXGTK_MAIN, /* main app window */ + MIXGTK_MIXVM_DIALOG, /* mixvm dialog */ + MIXGTK_MIXAL_DIALOG, /* mixal dialog */ + MIXGTK_DEVICES_DIALOG, /* devices dialog */ + MIXGTK_WORD_DIALOG, /* input dialog for a mix word */ + MIXGTK_ABOUT_DIALOG, + MIXGTK_GOTO_DIALOG, + MIXGTK_FONTSEL_DIALOG, /* font selection dialog */ + MIXGTK_DEVFORM_DIALOG, /* device format config dialog */ + MIXGTK_EXTERNPROG_DIALOG, /* external programs dialog */ + MIXGTK_SYMBOLS_DIALOG, /* symbol table dialog */ + MIXGTK_INPUT_DIALOG, /* console input dialog */ + MIXGTK_DEVDIR_DIALOG /* devices directory chooser */ +} mixgtk_dialog_id_t; + +/* enumeration of mixvm widget ids */ +typedef enum { + MIXGTK_WIDGET_STATUSBAR, + MIXGTK_WIDGET_ATTACH_BUTTON, + MIXGTK_WIDGET_NOTEBOOK, /* the notebook */ + MIXGTK_WIDGET_MIXVM, /* virtual machine */ + MIXGTK_WIDGET_MIXVM_CONTAINER, + MIXGTK_WIDGET_PROMPT, /* command prompt */ + MIXGTK_WIDGET_LOG, /* command output */ + MIXGTK_WIDGET_DEV_CONTAINER, + MIXGTK_WIDGET_MIXAL_CONTAINER, + MIXGTK_WIDGET_MIXAL_STATUSBAR, + 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_LAPTIME, + MIXGTK_WIDGET_PROGTIME, + MIXGTK_WIDGET_UPTIME, + MIXGTK_WIDGET_DEVICES, + MIXGTK_WIDGET_LOC, + MIXGTK_WIDGET_GOTO_ENTRY, + MIXGTK_WIDGET_NONE +} mixgtk_widget_id_t; + + +/* create a new factory from an xml glade file */ +extern gboolean +mixgtk_widget_factory_init (void); + +/* get a dialog */ +extern GtkWidget * +mixgtk_widget_factory_get_dialog (mixgtk_dialog_id_t dlg); + +/* get a widget */ +extern GtkWidget * +mixgtk_widget_factory_get (mixgtk_dialog_id_t dlg, mixgtk_widget_id_t widget); + +/* Get a widget by name */ +extern GtkWidget * +mixgtk_widget_factory_get_child_by_name (mixgtk_dialog_id_t dlg, + const gchar *name); + +#endif /* MIXGTK_WIDGETS_H */ + diff --git a/mixgtk/mixgtk_wm.c b/mixgtk/mixgtk_wm.c new file mode 100644 index 0000000..7821d0e --- /dev/null +++ b/mixgtk/mixgtk_wm.c @@ -0,0 +1,573 @@ +/* -*-c-*- -------------- mixgtk_wm.c : + * Implementation of the functions declared in mixgtk_wm.h + * ------------------------------------------------------------------ + * $Id: mixgtk_wm.c,v 1.12 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include "mixgtk_wm.h" + +#include "mixgtk_widgets.h" +#include "mixgtk_config.h" +#include "mixgtk_device.h" +#include "mixgtk_mixvm.h" +#include "mixgtk_mixal.h" +#include "mixgtk_widgets.h" +#include "mixgtk_cmd_dispatcher.h" +#include "mixgtk.h" + + +typedef struct window_info_t_ +{ + mixgtk_dialog_id_t dialog; + GtkWidget *widget; + GtkCheckMenuItem *menu; + const gchar *menu_name; + const gchar *config_key; + gboolean detached; + void (*detach) (void); + void (*attach) (void); +} window_info_t_; + +static const gchar *DETACH_YES_ = "Yes"; +static const gchar *DETACH_NO_ = "No"; +static GtkWidget *about_ = NULL; + +static GtkContainer *mixvm_container_ = NULL; +static GtkContainer *mixal_container_ = NULL; +static GtkContainer *dev_container_ = NULL; + +static const gchar *TB_MENU_NAME_ = "show_toolbars"; +static GtkCheckMenuItem *tb_menu_ = NULL; +static GtkNotebook *notebook_ = NULL; + +static mix_vm_t *vm_ = NULL; + +static void init_info_ (void); +static void init_notebook_ (void); +static void init_dispatcher_ (void); +static void init_mixvm_ (void); +static void init_mixal_ (void); +static void init_dev_ (void); +static void init_signals_ (void); +static void init_visibility_ (void); +static void init_tb_ (void); +static void init_about_ (void); +static void init_autosave_ (void); +static void show_toolbars_ (gboolean show); +static void add_page_ (GtkWidget *w, mixgtk_window_id_t id); +static void mixvm_attach_ (void); +static void mixvm_detach_ (void); +static void mixal_attach_ (void); +static void mixal_detach_ (void); +static void dev_attach_ (void); +static void dev_detach_ (void); +static void on_nb_switch_ (GtkNotebook *notebook, GtkWidget *page, + guint page_num, gpointer user_data); + +static window_info_t_ infos_[] = { + {MIXGTK_MIXVM_DIALOG, NULL, NULL, "detach_vm", "MIX.detach", + FALSE, mixvm_detach_, mixvm_attach_}, + {MIXGTK_MIXAL_DIALOG, NULL, NULL, "detach_source", "MIXAL.detach", + FALSE, mixal_detach_, mixal_attach_}, + {MIXGTK_DEVICES_DIALOG, NULL, NULL, "detach_dev", "Devices.detach", + FALSE, dev_detach_, dev_attach_} +}; + +static size_t INF_NO_ = sizeof (infos_) / sizeof (infos_[0]); + + +gboolean +mixgtk_wm_init (void) +{ + gint k; + + init_info_ (); + init_notebook_ (); + init_dispatcher_ (); + init_mixvm_ (); + init_mixal_ (); + init_dev_ (); + + for (k = 0; k < INF_NO_; ++k) + { + if (infos_[k].detached) + mixgtk_wm_detach_window (k); + else + mixgtk_wm_attach_window (k); + } + + init_tb_ (); + init_about_ (); + init_autosave_ (); + init_visibility_ (); + init_signals_ (); + + return TRUE; +} + +void +mixgtk_wm_detach_window (mixgtk_window_id_t w) +{ + if (w < INF_NO_) + { + (*(infos_[w].detach)) (); + infos_[w].detached = TRUE; + gtk_check_menu_item_set_active (infos_[w].menu, TRUE); + mixgtk_config_update (infos_[w].config_key, DETACH_YES_); + if (infos_[w].widget != NULL) gtk_widget_show (infos_[w].widget); + if (gtk_notebook_get_n_pages (notebook_) < 1) + gtk_widget_hide (GTK_WIDGET (notebook_)); + gtk_widget_show (mixgtk_widget_factory_get_dialog (infos_[w].dialog)); + } +} + +void +mixgtk_wm_attach_window (mixgtk_window_id_t w) +{ + if (w < INF_NO_) + { + gint page = gtk_notebook_page_num (notebook_, infos_[w].widget); + + gtk_widget_hide (mixgtk_widget_factory_get_dialog (infos_[w].dialog)); + + if (page < 0) (*(infos_[w].attach)) (); + + infos_[w].detached = FALSE; + gtk_check_menu_item_set_active (infos_[w].menu, FALSE); + mixgtk_config_update (infos_[w].config_key, DETACH_NO_); + if (gtk_notebook_get_n_pages (notebook_) == 1) + gtk_widget_show (GTK_WIDGET (notebook_)); + } +} + + + +/* callbacks */ +void +on_detach_clicked (GtkWidget *ignored) +{ + gint page = gtk_notebook_get_current_page (notebook_); + if (page >= 0) + { + gint k; + GtkWidget *w = gtk_notebook_get_nth_page (notebook_, page); + + for (k = 0; k < INF_NO_; ++k) + if (infos_[k].widget == w) mixgtk_wm_detach_window (k); + } +} + +void +on_attach_all_clicked () +{ + gint k; + for (k = INF_NO_; k > 0; --k) + if (infos_[k - 1].detached) mixgtk_wm_attach_window (k - 1); +} + +void +on_attach_toggled (GtkCheckMenuItem *item) +{ + gint k; + for (k = 0; k < INF_NO_; ++k) + if (item == infos_[k].menu) break; + g_return_if_fail (k < INF_NO_); + if (item->active) mixgtk_wm_detach_window (k); + else mixgtk_wm_attach_window (k); + mixgtk_config_update (infos_[k].config_key, + (item->active)? DETACH_YES_ : DETACH_NO_); +} + +void +on_window_hide (GtkWidget *w) +{ + gint k; + for (k = 0; k < INF_NO_; ++k) + if (w == mixgtk_widget_factory_get_dialog (infos_[k].dialog)) break; + g_return_if_fail (k < INF_NO_); + mixgtk_wm_attach_window (k); +} + +void +on_show_toolbars_toggled (GtkCheckMenuItem *item) +{ + if (item->active != mixgtk_config_show_toolbars ()) + show_toolbars_ (item->active); +} + +void +on_widget_attach (GtkWidget *ign, gpointer id) +{ + mixgtk_wm_attach_window (GPOINTER_TO_INT (id)); +} + + +/* about box */ +void +on_about_activate (GtkWidget *w, gpointer data) +{ + if (!about_) init_about_ (); + gtk_widget_show (about_); +} + + +static void +init_info_ (void) +{ + gint k; + for (k = 0; k < INF_NO_; ++k) + { + const gchar *txt; + + infos_[k].menu = + GTK_CHECK_MENU_ITEM + (mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN, + infos_[k].menu_name)); + g_assert (infos_[k].menu != NULL); + txt = mixgtk_config_get (infos_[k].config_key); + infos_[k].detached = txt && !g_ascii_strcasecmp (txt, DETACH_YES_); + } +} + +static void +init_notebook_ (void) +{ + notebook_ = + GTK_NOTEBOOK (mixgtk_widget_factory_get (MIXGTK_MAIN, + MIXGTK_WIDGET_NOTEBOOK)); + g_assert (notebook_ != NULL); + gtk_widget_show (GTK_WIDGET (notebook_)); +} + +static void +add_page_ (GtkWidget *page, mixgtk_window_id_t id) +{ + static const gchar *LABELS[] = { + N_("_Virtual machine"), N_("_Source"), N_("_Devices") + }; + + gint p = 0; + + g_assert (page != NULL); + g_assert (id < INF_NO_); + g_assert (notebook_ != NULL); + + if (id > MIXGTK_MIXVM_WINDOW) + { + if (id == MIXGTK_DEVICES_WINDOW) + p = gtk_notebook_get_n_pages (notebook_); + else + p = infos_[MIXGTK_MIXVM_WINDOW].detached ? 0 : 1; + } + + gtk_notebook_insert_page (notebook_, page, + gtk_label_new_with_mnemonic (LABELS[id]), + p); + gtk_notebook_set_current_page (notebook_, p); + gtk_widget_show (page); + gtk_widget_show (GTK_WIDGET (notebook_)); +} + +static void +init_signals_ (void) +{ + gint k; + for (k = 0; k < INF_NO_; ++k) + { + GObject *dialog = + G_OBJECT (mixgtk_widget_factory_get_dialog (infos_[k].dialog)); + + GObject *button = + G_OBJECT (mixgtk_widget_factory_get (infos_[k].dialog, + MIXGTK_WIDGET_ATTACH_BUTTON)); + + g_assert (dialog != NULL); + g_assert (button != NULL); + + g_signal_connect (button, "clicked", + G_CALLBACK (on_widget_attach), GINT_TO_POINTER (k)); + g_signal_connect (dialog, "destroy", + G_CALLBACK (on_window_hide), NULL); + g_signal_connect (dialog, "destroy_event", + G_CALLBACK (on_window_hide), NULL); + g_signal_connect (dialog, "delete_event", + G_CALLBACK (on_window_hide), NULL); + g_signal_connect (G_OBJECT (infos_[k].menu), "toggled", + G_CALLBACK (on_attach_toggled), NULL); + } + +} + +static void +init_visibility_ (void) +{ + gint k; + for (k = 0; k < INF_NO_; ++k) + if (infos_[k].detached) + gtk_widget_show (mixgtk_widget_factory_get_dialog (infos_[k].dialog)); + + if (gtk_notebook_get_n_pages (notebook_) > 0) + gtk_notebook_set_current_page (notebook_, 0); + + gtk_widget_show (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN)); +} + +static void +init_dispatcher_ (void) +{ + if (!mixgtk_cmd_dispatcher_init (MIXGTK_MAIN)) + g_assert (FALSE); + vm_ = mixgtk_cmd_dispatcher_get_vm (); + g_assert (vm_ != NULL); +} + +static void +init_mixvm_ (void) +{ + GtkContainer *vm = + GTK_CONTAINER + (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, MIXGTK_WIDGET_MIXVM)); + + mixvm_container_ = + GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, + MIXGTK_WIDGET_MIXVM_CONTAINER)); + + g_assert (mixvm_container_ != NULL); + + g_assert (vm != NULL); + g_object_ref (G_OBJECT (vm)); + infos_[MIXGTK_MIXVM_WINDOW].widget = GTK_WIDGET (vm); + + mixgtk_mixvm_init (vm_); + mixgtk_mixvm_update_vm_widgets (); + + gtk_widget_show (GTK_WIDGET (vm)); + +} + +static void +init_mixal_ (void) +{ + GtkWidget *page = gtk_scrolled_window_new (NULL, NULL); + GtkWidget *mixal = mixgtk_mixal_init (vm_); + + g_assert (page != NULL); + g_assert (mixal != NULL); + + g_object_ref (page); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add (GTK_CONTAINER (page), mixal); + + infos_[MIXGTK_MIXAL_WINDOW].widget = page; + + mixal_container_ = + GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_MIXAL_DIALOG, + MIXGTK_WIDGET_MIXAL_CONTAINER)); + + g_assert (mixal_container_ != NULL); + + gtk_container_add (mixal_container_, page); + + gtk_widget_show (mixal); + gtk_widget_show (page); + gtk_widget_show (GTK_WIDGET (mixal_container_)); +} + +static void +init_dev_ (void) +{ + GtkWidget *page = gtk_scrolled_window_new (NULL, NULL); + GtkWidget *devs = mixgtk_device_init (vm_); + + g_assert (page != NULL); + g_assert (devs != NULL); + + g_object_ref (page); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (page), devs); + + infos_[MIXGTK_DEVICES_WINDOW].widget = page; + + dev_container_ = + GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_DEVICES_DIALOG, + MIXGTK_WIDGET_DEV_CONTAINER)); + + g_assert (dev_container_ != NULL); + + gtk_container_add (dev_container_, page); + + gtk_widget_show (devs); + gtk_widget_show (page); +} + +static void +init_tb_ (void) +{ + tb_menu_ = GTK_CHECK_MENU_ITEM + (mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN, + TB_MENU_NAME_)); + g_assert (tb_menu_ != NULL); + + gtk_check_menu_item_set_active (tb_menu_, mixgtk_config_show_toolbars ()); + show_toolbars_ (mixgtk_config_show_toolbars ()); + + g_signal_connect (G_OBJECT (tb_menu_), "toggled", + G_CALLBACK (on_show_toolbars_toggled), NULL); +} + +static void +show_toolbars_ (gboolean show) +{ + static const gchar *HANDLE_NAME = "tb_handle"; + + int k; + + GtkWidget *handle = + mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN, HANDLE_NAME); + + if (show) + gtk_widget_show (handle); + else + gtk_widget_hide (handle); + + for (k = 0; k < INF_NO_; ++k) + { + GtkWidget *hd = + mixgtk_widget_factory_get_child_by_name (infos_[k].dialog, HANDLE_NAME); + if (show) gtk_widget_show (hd); else gtk_widget_hide (hd); + } + + mixgtk_config_set_show_toolbars (show); +} + +static void +init_autosave_ (void) +{ +#define AUTOSAVE_ITEM_ "save_on_exit" + + GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM + (mixgtk_widget_factory_get_child_by_name (MIXGTK_MAIN, AUTOSAVE_ITEM_)); + if (item) + { + gtk_check_menu_item_set_active (item, mixgtk_config_is_autosave ()); + } +} + +static void +init_about_ (void) +{ +#define VERSION_LABEL_ "version_label" +#define GPL_TEXT_ "gpl_text" + GtkWidget *label; + about_ = mixgtk_widget_factory_get_dialog (MIXGTK_ABOUT_DIALOG); + g_assert (about_ != NULL); + label = mixgtk_widget_factory_get_child_by_name (MIXGTK_ABOUT_DIALOG, + VERSION_LABEL_); + g_assert (label != NULL); + gtk_label_set_text (GTK_LABEL (label), VERSION); + gtk_widget_show (label); +} + +static void +mixvm_attach_ (void) +{ + gtk_container_remove (mixvm_container_, infos_[MIXGTK_MIXVM_WINDOW].widget); + add_page_ (infos_[MIXGTK_MIXVM_WINDOW].widget, MIXGTK_MIXVM_WINDOW); +} + +static void +mixvm_detach_ (void) +{ + gtk_widget_reparent (infos_[MIXGTK_MIXVM_WINDOW].widget, + GTK_WIDGET (mixvm_container_)); +} + +static void +mixal_attach_ (void) +{ + static GtkStatusbar *stat = NULL; + + if (stat == NULL) + { + stat = + GTK_STATUSBAR + (mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_STATUSBAR)); + g_assert (stat); + + g_signal_connect (G_OBJECT (notebook_), "switch-page", + G_CALLBACK (on_nb_switch_), NULL); + } + + mixgtk_mixal_reparent (stat); + gtk_container_remove (mixal_container_, infos_[MIXGTK_MIXAL_WINDOW].widget); + add_page_ (infos_[MIXGTK_MIXAL_WINDOW].widget, MIXGTK_MIXAL_WINDOW); +} + +static void +mixal_detach_ (void) +{ + static GtkStatusbar *stat = NULL; + + if (stat == NULL) + { + stat = + GTK_STATUSBAR + (mixgtk_widget_factory_get (MIXGTK_MIXAL_DIALOG, + MIXGTK_WIDGET_MIXAL_STATUSBAR)); + g_assert (stat); + } + + mixgtk_mixal_reparent (stat); + gtk_widget_reparent (infos_[MIXGTK_MIXAL_WINDOW].widget, + GTK_WIDGET (mixal_container_)); +} + +static void +dev_attach_ (void) +{ + gtk_container_remove (dev_container_, infos_[MIXGTK_DEVICES_WINDOW].widget); + add_page_ (infos_[MIXGTK_DEVICES_WINDOW].widget, MIXGTK_DEVICES_WINDOW); +} + +static void +dev_detach_ (void) +{ + gtk_widget_reparent (infos_[MIXGTK_DEVICES_WINDOW].widget, + GTK_WIDGET (dev_container_)); +} + +static void +on_nb_switch_ (GtkNotebook *notebook, GtkWidget *page, + guint page_num, gpointer user_data) +{ + if (!(infos_[MIXGTK_MIXAL_WINDOW].detached) + && (page != infos_[MIXGTK_MIXAL_WINDOW].widget)) + mixgtk_mixal_pop_status (); +} + + diff --git a/mixgtk/mixgtk_wm.h b/mixgtk/mixgtk_wm.h new file mode 100644 index 0000000..878eca6 --- /dev/null +++ b/mixgtk/mixgtk_wm.h @@ -0,0 +1,46 @@ +/* -*-c-*- ---------------- mixgtk_wm.h : + * Functions for window management + * ------------------------------------------------------------------ + * $Id: mixgtk_wm.h,v 1.5 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGTK_WM_H +#define MIXGTK_WM_H + +#include "mixgtk.h" + +typedef enum { + MIXGTK_MIXVM_WINDOW, + MIXGTK_MIXAL_WINDOW, + MIXGTK_DEVICES_WINDOW +} mixgtk_window_id_t; + +extern gboolean +mixgtk_wm_init (void); + +extern void +mixgtk_wm_attach_window (mixgtk_window_id_t w); + +extern void +mixgtk_wm_detach_window (mixgtk_window_id_t w); + +#endif /* MIXGTK_WM_H */ + diff --git a/mixguile/Makefile.am b/mixguile/Makefile.am new file mode 100644 index 0000000..cdafcba --- /dev/null +++ b/mixguile/Makefile.am @@ -0,0 +1,43 @@ +## 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. + +# $Id: Makefile.am,v 1.6 2001/09/30 20:29:30 jao Exp $ + +SCM_FILES = mixguile.scm mixguile-commands.scm mixguile-vm-stat.scm +EXTRA_DIST = $(SCM_FILES) + +noinst_LIBRARIES = libmixguile.a + +if MAKE_GUILE + +SCM_PATHS = -DSCM_FILE=\""$(pkgdatadir)/mixguile.scm"\"\ + -DLOCAL_SCM_FILE=\"mixguile.scm\" + +pkgdata_DATA = $(SCM_FILES) +INCLUDES = -I$(includedir) -I$(top_srcdir) $(SCM_PATHS) +libmixguile_a_INCLUDES = -I$(includedir) -I$(top_srcdir) \ + -DG_LOG_DOMAIN=\"libmixguile\" +libmixguile_a_SOURCES = mixguile.h mixguile.c \ + mixguile_cmd_dispatcher.h mixguile_cmd_dispatcher.c \ + xmixguile_cmd_dispatcher.h xmixguile_cmd_dispatcher.c + +bin_PROGRAMS = mixguile +mixguile_LDADD = $(top_builddir)/mixlib/libmix.a \ + $(top_builddir)/lib/libreplace.a \ + $(top_builddir)/mixguile/libmixguile.a $(INTLLIBS) +mixguile_SOURCES = mixguile_main.c + +else + +libmixguile_a_SOURCES = + +endif diff --git a/mixguile/mixguile-commands.scm b/mixguile/mixguile-commands.scm new file mode 100644 index 0000000..bc1aeb2 --- /dev/null +++ b/mixguile/mixguile-commands.scm @@ -0,0 +1,254 @@ +;; -*-scheme-*- -------------- mixguile-commands.scm : +; mixvm commands implementation using the mixvm-cmd primitive +; ------------------------------------------------------------------ +; $Id: mixguile-commands.scm,v 1.5 2005/09/20 19:43:14 jao Exp $ +; ------------------------------------------------------------------ +; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +; +;; + +;; auxiliar functions for argument conversion +(define argsym->string + (lambda (arg) + (cond ((symbol? arg) (symbol->string arg)) + ((string? arg) arg) + (else (error "Wrong argument type" arg))))) + +(define argnsym->string + (lambda (arg) + (cond ((null? arg) "") + ((pair? arg) (argsym->string (car arg))) + (else (argsym->string arg))))) + +(define argnum->string + (lambda (arg) + (cond ((number? arg) (number->string arg)) + ((string? arg) arg) + (else (error "Wrong argument type" arg))))) + +(define argnnum->string + (lambda (arg) + (cond ((null? arg) "") + ((pair? arg) (argnum->string (car arg))) + (else (argnum->string arg))))) + +;;; mixvm commands + +; preg +(define mix-preg + (lambda (. reg) + (mixvm-cmd "preg" (argnsym->string reg)))) + +; sreg +(define mix-sreg + (lambda (reg val) (mixvm-cmd "sreg" (string-append (argsym->string reg) + " " + (argnum->string val))))) + +; pmem +(define mix-pmem + (lambda (from . to) + (cond ((null? to) (mixvm-cmd "pmem" (argnum->string from))) + (else (mixvm-cmd "pmem" + (string-append (argnum->string from) + "-" + (argnnum->string to))))))) + +; smem +(define mix-smem + (lambda (cell val) (mixvm-cmd "smem" (string-append (argnum->string cell) + " " + (argnum->string val))))) + +; pall +(define mix-pall (lambda () (mixvm-cmd "pall" ""))) + +; pc +(define mix-pc (lambda () (mixvm-cmd "pc" ""))) + +; pflags +(define mix-pflags (lambda () (mixvm-cmd "pflags" ""))) + +; sover +(define mix-sover + (lambda (val) + (mixvm-cmd "sover" (if val "T" "F")))) + +; psym +(define mix-psym + (lambda (. sym) + (mixvm-cmd "psym" (argnsym->string sym)))) + +; ssym +(define mix-ssym + (lambda (sym value) + (mixvm-cmd "ssym" + (string-append + (argsym->string sym) " " (argnum->string value))))) + +; run +(define mix-run + (lambda (. file) + (mixvm-cmd "run" (argnsym->string file)))) + +; next +(define mix-next + (lambda (. no) + (mixvm-cmd "next" (argnnum->string no)))) + +; load +(define mix-load + (lambda (file) + (mixvm-cmd "load" (argsym->string file)))) + +; pstat +(define mix-pstat (lambda () (mixvm-cmd "pstat" ""))) + +; compile +(define mix-compile + (lambda (. file) + (mixvm-cmd "compile" (argnsym->string file)))) + +; devdir +(define mix-sddir + (lambda (dir) + (mixvm-cmd "sddir" dir))) + +(define mix-pddir (lambda () (mixvm-cmd "pddir" ""))) + +; edit +(define mix-edit + (lambda (. file) + (mixvm-cmd "edit" (argnsym->string file)))) + +; help +(define mix-help + (lambda (. cmd) + (mixvm-cmd "help" (argnsym->string cmd)))) + +; pasm +(define mix-pasm (lambda () (mixvm-cmd "pasm" ""))) + +; sasm +(define mix-sasm + (lambda (path) + (mixvm-cmd "sasm" (argsym->string path)))) + +; pedit +(define mix-pedit (lambda () (mixvm-cmd "pedit" ""))) + +; sedit +(define mix-sedit + (lambda (path) + (mixvm-cmd "sedit" (argsym->string path)))) + +; sbp +(define mix-sbp + (lambda (line) + (mixvm-cmd "sbp" (argnum->string line)))) + +; sbp +(define mix-pline + (lambda (. no) + (mixvm-cmd "pline" (argnnum->string no)))) + +; cbp +(define mix-cbp + (lambda (line) + (mixvm-cmd "cbp" (argnum->string line)))) + +; sbpa +(define mix-sbpa + (lambda (addr) + (mixvm-cmd "sbpa" (argnum->string addr)))) + +; cbpa +(define mix-cbpa + (lambda (addr) + (mixvm-cmd "cbpa" (argnum->string addr)))) + + +; sbpc +(define mix-sbpc (lambda () (mixvm-cmd "sbpc" ""))) + +; cbpc +(define mix-cbpc (lambda () (mixvm-cmd "cbpc" ""))) + +; sbpo +(define mix-sbpo (lambda () (mixvm-cmd "sbpo" ""))) + +; cbpo +(define mix-cbpo (lambda () (mixvm-cmd "cbpo" ""))) + +; sbpm +(define mix-sbpm + (lambda (cell) + (mixvm-cmd "sbpm" (argnum->string cell)))) + +; cbpm +(define mix-cbpm + (lambda (cell) + (mixvm-cmd "cbpm" (argnum->string cell)))) + +; sbpr +(define mix-sbpr + (lambda (reg) + (mixvm-cmd "sbpr" (argsym->string reg)))) + +; cbpr +(define mix-cbpr + (lambda (reg) + (mixvm-cmd "cbpr" (argsym->string reg)))) + +; pbt +(define mix-pbt + (lambda (. num) + (mixvm-cmd "pbt" (argnnum->string num)))) + +; timing +(define mix-stime + (lambda (on) + (mixvm-cmd "stime" (if on "on" "off")))) + +(define mix-ptime (lambda () (mixvm-cmd "ptime" ""))) + +; timing +(define mix-strace + (lambda (on) + (mixvm-cmd "strace" (if on "on" "off")))) + +; logging +(define mix-slog + (lambda (on) + (mixvm-cmd "slog" (if on "on" "off")))) + +; w2d +(define mix-w2d + (lambda (w) + (mixvm-cmd "w2d" w))); + +; weval +(define mix-weval + (lambda (exp) + (mixvm-cmd "weval" (argsym->string exp)))) + +; pprog +(define mix-pprog (lambda () (mixvm-cmd "pprog" ""))) + +; sprog +(define mix-psrc (lambda () (mixvm-cmd "psrc" ""))) + diff --git a/mixguile/mixguile-vm-stat.scm b/mixguile/mixguile-vm-stat.scm new file mode 100644 index 0000000..1887b4c --- /dev/null +++ b/mixguile/mixguile-vm-stat.scm @@ -0,0 +1,71 @@ +;; -*-scheme-*- -------------- mixguile-vm-stat.scm : +; mixvm status functions +; ------------------------------------------------------------------ +; $Id: mixguile-vm-stat.scm,v 1.4 2005/09/20 19:43:14 jao Exp $ +; ------------------------------------------------------------------ +; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +; +;; + +;; possible status index +(define mix-status-values (vector 'MIX_ERROR + 'MIX_BREAK + 'MIX_COND_BREAK + 'MIX_HALTED + 'MIX_RUNNING + 'MIX_LOADED + 'MIX_EMPTY)) +;; return status as a simbol +(define mix-vm-status (lambda () (vector-ref mix-status-values (mixvm-status)))) + +;; check for a given status +(define mix-vm-status? + (lambda (status) (eq? status (mix-vm-status)))) + +;; predicates for each possible status +(define mix-vm-error? (lambda () (mix-vm-status? 'MIX_ERROR))) +(define mix-vm-break? (lambda () (mix-vm-status? 'MIX_BREAK))) +(define mix-vm-cond-break? (lambda () (mix-vm-status? 'MIX_COND_BREAK))) +(define mix-vm-halted? (lambda () (mix-vm-status? 'MIX_HALTED))) +(define mix-vm-running? (lambda () (mix-vm-status? 'MIX_RUNNING))) +(define mix-vm-loaded? (lambda () (mix-vm-status? 'MIX_LOADED))) +(define mix-vm-empty? (lambda () (mix-vm-status? 'MIX_EMPTY))) + + +;; define hooks on break conditions + +(define mix-make-conditional-hook + (lambda (test hook) + (lambda (arglist) + (if (test) (hook (mix-src-line-no) (mix-loc)))))) + +(define mix-add-run-next-hook + (lambda (hook) + (mix-add-post-hook 'run hook) + (mix-add-post-hook 'next hook))) + + +(define mix-add-break-hook + (lambda (hook) + (mix-add-run-next-hook (mix-make-conditional-hook mix-vm-break? hook)))) + +(define mix-add-cond-break-hook + (lambda (hook) + (mix-add-run-next-hook (mix-make-conditional-hook + mix-vm-cond-break? hook)))) + + diff --git a/mixguile/mixguile.c b/mixguile/mixguile.c new file mode 100644 index 0000000..f37424f --- /dev/null +++ b/mixguile/mixguile.c @@ -0,0 +1,124 @@ +/* -*-c-*- -------------- mixguile.c : + * Implementation of the functions declared in mixguile.h + * ------------------------------------------------------------------ + * $Id: mixguile.c,v 1.8 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include "mixguile_cmd_dispatcher.h" +#include "mixguile.h" + +static mixguile_cmd_dispatcher_t *dispatcher_ = NULL; +static mix_vm_cmd_dispatcher_t *vm_dispatcher_ = NULL; +static main_func_t main_fun_; +static gboolean init_file_; + +/* do local initialisation and enter the user provided main */ + +static void +real_main_ (int argc, char *argv[]) +{ + if (vm_dispatcher_) + { + mixguile_set_cmd_dispatcher (vm_dispatcher_); + mixguile_load_bootstrap (init_file_); + } + (*main_fun_)(argc, argv); +} + +/* + initialise the guile command dispatcher and enter the provided + main function. +*/ +void +mixguile_init (int argc, char *argv[], gboolean initfile, + main_func_t main_fun, + mix_vm_cmd_dispatcher_t *dis) +{ + main_fun_ = main_fun; + vm_dispatcher_ = dis; + init_file_ = initfile; + gh_enter (argc, argv, real_main_); +} + +/* load bootstrap file */ +void +mixguile_load_bootstrap (gboolean loadlocal) +{ + const gchar *scmfile = SCM_FILE; + gchar *lscmfile = g_strconcat (g_get_home_dir (), G_DIR_SEPARATOR_S, + MIX_CONFIG_DIR, G_DIR_SEPARATOR_S, + LOCAL_SCM_FILE, NULL); + + if (access (scmfile, R_OK) && access ((scmfile = LOCAL_SCM_FILE), R_OK)) + { + g_warning (_("mixguile bootstrap file %s not found\n"), SCM_FILE); + scmfile = NULL; + } + else + mixguile_interpret_file (scmfile); + + if (loadlocal && !access (lscmfile, R_OK)) + { + mixguile_interpret_file (lscmfile); + } + + g_free (lscmfile); +} + +/* enter the guile repl */ +void +mixguile_enter_repl (int argc, char *argv[]) +{ + gh_repl (argc, argv); +} + +/* set the command dispatcher */ +void +mixguile_set_cmd_dispatcher (mix_vm_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + if (dispatcher_) mixguile_cmd_dispatcher_delete (dispatcher_); + vm_dispatcher_ = dis; + dispatcher_ = mixguile_cmd_dispatcher_new (dis); + g_assert (dispatcher_); +} + +/* access the mixguile comand dispatcher */ +mix_vm_cmd_dispatcher_t * +mixguile_get_cmd_dispatcher (void) +{ + return mixguile_cmd_dispatcher_get_vm_dispatcher (dispatcher_); +} + +/* execute a string or file using the guile interpreter */ +void +mixguile_interpret_file (const gchar *path) +{ + mixguile_cmd_dispatcher_interpret_file (dispatcher_, path); +} + +void +mixguile_interpret_command (const gchar *command) +{ + mixguile_cmd_dispatcher_interpret_command (dispatcher_, command); +} diff --git a/mixguile/mixguile.h b/mixguile/mixguile.h new file mode 100644 index 0000000..c2ef492 --- /dev/null +++ b/mixguile/mixguile.h @@ -0,0 +1,72 @@ +/* -*-c-*- ---------------- mixguile.h : + * Interface to the mixguile interpreter. + * ------------------------------------------------------------------ + * $Id: mixguile.h,v 1.6 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGUILE_H +#define MIXGUILE_H + +#include +#include +#include + +/* the main function type */ +typedef void (*main_func_t) (int argc, char *argv[]); + + +/* enter and do the initialisation manually inside the guile world */ +#define mixguile_enter(argc,argv,main_fun) gh_enter (argc, argv, main_fun) + +/* load mixguile startup file */ +extern void +mixguile_load_bootstrap (gboolean localinit); + +/* + initialise the guile command dispatcher and enter the provided + main function. +*/ +extern void +mixguile_init (int argc, char *argv[], gboolean initfile, main_func_t main_fun, + mix_vm_cmd_dispatcher_t *dis); + +/* set the command dispatcher */ +extern void +mixguile_set_cmd_dispatcher (mix_vm_cmd_dispatcher_t *dis); + +/* enter the guile repl */ +extern void +mixguile_enter_repl (int argc, char *argv[]); + +/* access the comand dispatcher */ +extern mix_vm_cmd_dispatcher_t * +mixguile_get_cmd_dispatcher (void); + +/* execute a string or file using the guile interpreter */ +extern void +mixguile_interpret_file (const gchar *path); + +extern void +mixguile_interpret_command (const gchar *command); + + +#endif /* MIXGUILE_H */ + diff --git a/mixguile/mixguile.scm b/mixguile/mixguile.scm new file mode 100644 index 0000000..4e7dcbe --- /dev/null +++ b/mixguile/mixguile.scm @@ -0,0 +1,25 @@ +;; -*-scheme-*- -------------- mixguile.scm : +; mixguile bootstrap file +; ------------------------------------------------------------------ +; Last change: Time-stamp: "01/09/05 01:05:29 jao" +; ------------------------------------------------------------------ +; 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +; +;; + +(load "mixguile-commands.scm") +(load "mixguile-vm-stat.scm") diff --git a/mixguile/mixguile_cmd_dispatcher.c b/mixguile/mixguile_cmd_dispatcher.c new file mode 100644 index 0000000..2cc243b --- /dev/null +++ b/mixguile/mixguile_cmd_dispatcher.c @@ -0,0 +1,122 @@ +/* -*-c-*- -------------- mixguile_cmd_dispatcher.c : + * Implementation of the functions declared in mixguile_cmd_dispatcher.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "01/08/22 02:29:34 jao" + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include + +#include +#include "mixguile.h" +#include "xmixguile_cmd_dispatcher.h" + +#define SCM_CMD "scm" +#define SCMF_CMD "scmf" + +/*local commands */ +static gboolean +cmd_scm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + (void) gh_eval_str_with_catch ((char *)arg, scm_handle_by_message_noexit); + return TRUE; +} + +static gboolean +cmd_scmf_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + (void) gh_eval_file_with_catch ((char *)arg, scm_handle_by_message_noexit); + return TRUE; +} + +static mix_vm_command_info_t commands_[] = { + { SCM_CMD, cmd_scm_, N_("Eval Scheme command using Guile"), "scm COMMAND"}, + { SCMF_CMD, cmd_scmf_, N_("Eval Scheme file using Guile"), "scm PATH"}, + {NULL} +}; + +/* create/destroy cmd dispatcher */ +mixguile_cmd_dispatcher_t * +mixguile_cmd_dispatcher_new (mix_vm_cmd_dispatcher_t *dis) +{ + static gboolean REGISTERED = FALSE; + mixguile_cmd_dispatcher_t *result = NULL; + int k = 0; + + g_return_val_if_fail (dis != NULL, NULL); + + if (!REGISTERED) + { + register_scm_commands_ (DEFAULT_SCM_COMMANDS_); + REGISTERED = TRUE; + } + + result = g_new (mixguile_cmd_dispatcher_t, 1); + result->dispatcher = dis; + + while (commands_[k].name) + { + mix_vm_cmd_dispatcher_register_new (dis, commands_ + k); + ++k; + } + + register_cmd_dispatcher_ (result); + + return result; +} + + +void +mixguile_cmd_dispatcher_delete (mixguile_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + mix_vm_cmd_dispatcher_delete (dis->dispatcher); +} + +/* get the underlying vm dispatcher */ +mix_vm_cmd_dispatcher_t * +mixguile_cmd_dispatcher_get_vm_dispatcher (const mixguile_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis != NULL, NULL); + return dis->dispatcher; +} + +void +mixguile_cmd_dispatcher_interpret_file (mixguile_cmd_dispatcher_t *dis, + const gchar *path) +{ + g_return_if_fail (dis != NULL); + g_return_if_fail (path != NULL); + mix_vm_cmd_dispatcher_dispatch_split_text (dis->dispatcher, + SCMF_CMD, path); +} + +void +mixguile_cmd_dispatcher_interpret_command (mixguile_cmd_dispatcher_t *dis, + const gchar *command) +{ + g_return_if_fail (dis != NULL); + g_return_if_fail (command != NULL); + mix_vm_cmd_dispatcher_dispatch_split_text (dis->dispatcher, + SCM_CMD, command); +} + diff --git a/mixguile/mixguile_cmd_dispatcher.h b/mixguile/mixguile_cmd_dispatcher.h new file mode 100644 index 0000000..1b10510 --- /dev/null +++ b/mixguile/mixguile_cmd_dispatcher.h @@ -0,0 +1,57 @@ +/* -*-c-*- ---------------- mixguile_cmd_dispatcher.h : + * Command dispatcher with guile support + * ------------------------------------------------------------------ + * Last change: Time-stamp: <01/08/22 01:15:23 jao> + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXGUILE_CMD_DISPATCHER_H +#define MIXGUILE_CMD_DISPATCHER_H + +#include +#include + +/* the guile command dispatcher type */ +typedef struct mixguile_cmd_dispatcher_t mixguile_cmd_dispatcher_t; + +/* create/destroy cmd dispatcher */ +extern mixguile_cmd_dispatcher_t * +mixguile_cmd_dispatcher_new (mix_vm_cmd_dispatcher_t *dis); + +extern void +mixguile_cmd_dispatcher_delete (mixguile_cmd_dispatcher_t *dis); + +/* get the underlying vm dispatcher */ +extern mix_vm_cmd_dispatcher_t * +mixguile_cmd_dispatcher_get_vm_dispatcher (const + mixguile_cmd_dispatcher_t *disp); + +/* interpret commands from file or string */ +extern void +mixguile_cmd_dispatcher_interpret_file (mixguile_cmd_dispatcher_t *dis, + const gchar *path); + +extern void +mixguile_cmd_dispatcher_interpret_command (mixguile_cmd_dispatcher_t *dis, + const gchar *command); + + +#endif /* MIXGUILE_CMD_DISPATCHER_H */ + diff --git a/mixguile/mixguile_main.c b/mixguile/mixguile_main.c new file mode 100644 index 0000000..22e65be --- /dev/null +++ b/mixguile/mixguile_main.c @@ -0,0 +1,94 @@ +/* -*-c-*- -------------- mixguile_main.c : + * Main function for mixguile, the MIX Guile shell + * ------------------------------------------------------------------ + * $Id: mixguile_main.c,v 1.6 2005/09/20 19:43:14 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include "mixguile.h" + + +#ifdef HAVE_GETOPT_LONG +# include +#else +# include +#endif /* HAVE_GETOPT_LONG */ + +enum { + VER_OPT = 'v', + NOINIT_OPT = 'q', +}; + +static const char *options_ = "vq"; + +static struct option long_options_[] = +{ + {"version", no_argument, 0, VER_OPT}, + {0, 0, 0, 0} +}; + +int +main (int argc, char *argv[]) +{ + const gchar *CONFIG_FILE = "mixvm.config"; + mix_config_t *config; + mix_vm_cmd_dispatcher_t *dis; + int c; + + gboolean initfile = TRUE; + + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + /* prevent getopt printing a message for unknown options (stored in optopt) */ + opterr = 0; + + 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 VER_OPT: + mix_print_license ("mixguile, Scheme MIX Virtual Machine"); + return EXIT_SUCCESS; + case NOINIT_OPT: + initfile = FALSE; + break; + default: + /* let guile try to understand the option */ + break; + } + } + + mix_init_lib (); + + config = mix_config_new (NULL, CONFIG_FILE); + dis = mix_vm_cmd_dispatcher_new_with_config (stdout, stderr, config); + mixguile_init (argc, argv, initfile, mixguile_enter_repl, dis); + + return EXIT_SUCCESS; /* never reached */ +} diff --git a/mixguile/xmixguile_cmd_dispatcher.c b/mixguile/xmixguile_cmd_dispatcher.c new file mode 100644 index 0000000..2ccd19c --- /dev/null +++ b/mixguile/xmixguile_cmd_dispatcher.c @@ -0,0 +1,558 @@ +/* -*-c-*- -------------- xmixguile_cmd_dispatcher.c : + * Implementation of the functions declared in xmixguile_cmd_dispatcher.h + * ------------------------------------------------------------------ + * $Id: xmixguile_cmd_dispatcher.c,v 1.14 2005/09/20 19:50:26 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include + +#include "xmixguile_cmd_dispatcher.h" + +/* cmd dispatcher for use within the scm commands */ +static mixguile_cmd_dispatcher_t *dispatcher_; +static mix_vm_cmd_dispatcher_t *vm_dispatcher_; +static mix_vm_t *vm_; + +/* register a NULL-terminated list of scm commands */ +void +register_scm_commands_ (const scm_command_t *commands) +{ + int k = 0; + g_return_if_fail (commands != NULL); + while (commands[k].name) + { + gh_new_procedure (commands[k].name, commands[k].func, + commands[k].argno, commands[k].opt_argno, + commands[k].restp); + ++k; + } +} + +/* register the mixvm cmd dispatcher to use with commands */ +void +register_cmd_dispatcher_ (mixguile_cmd_dispatcher_t *dis) +{ + g_return_if_fail (dis != NULL); + dispatcher_ = dis; + vm_dispatcher_ = mixguile_cmd_dispatcher_get_vm_dispatcher (dis); + vm_ = (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (vm_dispatcher_); +} + +/* commands */ +static SCM +mixvm_cmd_ (SCM cmd, SCM arg) +{ + char *com = NULL, *argu = NULL; + unsigned int len; + gboolean result; + + SCM_ASSERT (SCM_STRINGP (cmd) || SCM_SYMBOLP (cmd), + cmd, SCM_ARG1, "mixvm-cmd"); + SCM_ASSERT (SCM_STRINGP (arg) || SCM_SYMBOLP (arg), + arg, SCM_ARG2, "mixvm-cmd"); + + SCM_DEFER_INTS; + com = gh_scm2newstr (cmd, &len); + argu = gh_scm2newstr (arg, &len); + result = mix_vm_cmd_dispatcher_dispatch (vm_dispatcher_, + mix_vm_command_from_string (com), + argu); + g_free (com); + g_free (argu); + + SCM_ALLOW_INTS; + + return SCM_UNSPECIFIED; +} + +static SCM +mixvm_status_ (void) +{ + return gh_long2scm (mix_vm_get_run_status (vm_)); +} + +static SCM +mix_last_result_ (void) +{ + return gh_bool2scm (mix_vm_cmd_dispatcher_get_last_result (vm_dispatcher_)); +} + +static long +word_to_long_ (mix_word_t word) +{ + long result = mix_word_magnitude (word); + return mix_word_is_negative (word) ? -result : result; +} + +static long +short_to_long_ (mix_short_t s) +{ + long result = mix_short_magnitude (s); + return mix_short_is_negative (s) ? -result : result; +} + +static SCM +mix_reg_ (SCM reg) +{ + char *regis; + unsigned int len; + long val = MIX_WORD_MAX + 1; + + SCM_ASSERT (SCM_STRINGP (reg) || SCM_SYMBOLP (reg), reg, SCM_ARG1, "mix-reg"); + + SCM_DEFER_INTS; + if (SCM_SYMBOLP (reg)) reg = scm_symbol_to_string (reg); + regis = gh_scm2newstr (reg, &len); + switch (regis[0]) + { + case 'A': + val = word_to_long_ (mix_vm_get_rA (vm_)); break; + case 'X': + val = word_to_long_ (mix_vm_get_rX (vm_)); break; + case 'J': + val = short_to_long_ (mix_vm_get_rJ (vm_)); break; + case 'I': + { + int i = regis[1] - '0'; + if (i > 0 && i < 7) val = short_to_long_ (mix_vm_get_rI (vm_, i)); + } + break; + default: + break; + } + g_free (regis); + + SCM_ALLOW_INTS; + + SCM_ASSERT (val <= MIX_WORD_MAX, reg, SCM_ARG1, "mix-reg"); + + return gh_long2scm (val); +} + +static SCM +mix_set_reg_ (SCM reg, SCM value) +{ + char *regis; + unsigned int len; + long val; + gboolean result = TRUE; + + SCM_ASSERT (SCM_STRINGP (reg) || SCM_SYMBOLP (reg), reg, SCM_ARG1, + "mix-set-reg!"); + SCM_ASSERT (SCM_NUMBERP (value), value, SCM_ARG2, "mix-set-reg!"); + + SCM_DEFER_INTS; + if (SCM_SYMBOLP (reg)) reg = scm_symbol_to_string (reg); + regis = gh_scm2newstr (reg, &len); + val = gh_scm2long (value); + switch (regis[0]) + { + case 'A': + mix_vm_set_rA (vm_, mix_word_new (val)); break; + case 'X': + mix_vm_set_rX (vm_, mix_word_new (val)); break; + case 'J': + mix_vm_set_rJ (vm_, mix_short_new (val)); break; + case 'I': + { + int i = regis[1] - '0'; + if (i > 0 && i < 7) mix_vm_set_rI (vm_, i, mix_short_new (val)); + else result = FALSE; + } + break; + default: + result = FALSE; break; + } + g_free (regis); + + SCM_ALLOW_INTS; + + SCM_ASSERT (result, reg, SCM_ARG1, "mix-set-reg!"); + + return gh_symbol2scm ("ok"); +} + +static SCM +mix_cell_ (SCM no) +{ + int cell; + long result; + + SCM_ASSERT (SCM_NUMBERP (no), no, SCM_ARG1, "mix-cell"); + cell = gh_scm2int (no); + SCM_ASSERT (cell < MIX_VM_CELL_NO, no, SCM_ARG1, "mix-cell"); + result = word_to_long_ (mix_vm_get_addr_contents (vm_, cell)); + return gh_long2scm (result); +} + +static SCM +mix_set_cell_ (SCM no, SCM val) +{ + int cell; + long result; + + SCM_ASSERT (SCM_NUMBERP (no), no, SCM_ARG1, "mix-set-cell!"); + SCM_ASSERT (SCM_NUMBERP (val), no, SCM_ARG2, "mix-set-cell!"); + cell = gh_scm2int (no); + SCM_ASSERT (cell < MIX_VM_CELL_NO, no, SCM_ARG1, "mix-set-cell!"); + result = gh_scm2long (val); + mix_vm_set_addr_contents (vm_, cell, mix_word_new (result)); + return gh_symbol2scm ("ok"); +} + +static SCM +mix_over_ (void) +{ + return gh_bool2scm (mix_vm_get_overflow (vm_)); +} + +static SCM +mix_set_over_ (SCM over) +{ + mix_vm_set_overflow (vm_, gh_scm2bool (over)); + return gh_symbol2scm ("ok"); +} + +static SCM +mix_loc_ (void) +{ + return gh_long2scm (mix_vm_get_prog_count (vm_)); +} + +static SCM +mix_cmp_ (void) +{ + gchar *result = NULL; + switch (mix_vm_get_cmpflag (vm_)) + { + case mix_LESS: result = "L"; break; + case mix_EQ: result = "E"; break; + case mix_GREAT: result = "G"; break; + default: g_assert_not_reached (); + } + return gh_symbol2scm (result); +} + +static SCM +mix_set_cmp_ (SCM value) +{ + gchar *val = NULL; + unsigned int len; + mix_cmpflag_t result = -1; + + SCM_ASSERT (SCM_STRINGP (value) || SCM_SYMBOLP (value), value, SCM_ARG1, + "mix-set-cmp!"); + + SCM_DEFER_INTS; + val = gh_scm2newstr (value, &len); + if (strlen (val) == 1) + { + switch (val[0]) + { + case 'L': result = mix_LESS; break; + case 'E': result = mix_EQ; break; + case 'G': result = mix_GREAT; break; + default: break; + } + } + g_free (val); + SCM_ALLOW_INTS; + SCM_ASSERT (result != -1, value, SCM_ARG1, "mix-set-cmp!"); + mix_vm_set_cmpflag (vm_, result); + return gh_symbol2scm ("ok"); +} + +static SCM +mix_src_name_ (void) +{ + const gchar *path = mix_vm_cmd_dispatcher_get_src_file_path (vm_dispatcher_); + return gh_str02scm (path? g_path_get_basename (path) : ""); +} + +static SCM +mix_src_path_ (void) +{ + const gchar *path = mix_vm_cmd_dispatcher_get_src_file_path (vm_dispatcher_); + return gh_str02scm (path? (char *)path : ""); +} + +static SCM +mix_prog_name_ (void) +{ + const gchar *path = mix_vm_cmd_dispatcher_get_program_path (vm_dispatcher_); + return gh_str02scm (path? g_path_get_basename (path) : ""); +} + +static SCM +mix_prog_path_ (void) +{ + const gchar *path = mix_vm_cmd_dispatcher_get_program_path (vm_dispatcher_); + return gh_str02scm (path? (char *)path : ""); +} + +static SCM +mix_ddir_ (void) +{ + return gh_str02scm ((char *)mix_device_get_dir ()); +} + +static SCM +mix_uptime_ (void) +{ + return gh_long2scm (mix_vm_cmd_dispatcher_get_uptime (vm_dispatcher_)); +} + +static SCM +mix_progtime_ (void) +{ + return gh_long2scm (mix_vm_cmd_dispatcher_get_progtime (vm_dispatcher_)); +} + +static SCM +mix_laptime_ (void) +{ + return gh_long2scm (mix_vm_cmd_dispatcher_get_laptime (vm_dispatcher_)); +} + +static SCM +mix_src_line_ (SCM opt) +{ + gulong no = 0; + const gchar *line = ""; + if (opt != SCM_UNDEFINED) + { + SCM_ASSERT (SCM_NUMBERP (opt), opt, SCM_ARG1, "mix-src-line"); + no = gh_scm2long (opt); + } + else + no = mix_vm_cmd_dispatcher_get_src_file_lineno (vm_dispatcher_); + + SCM_ASSERT (line >= 0, opt, SCM_ARG1, "mix-src-line"); + + if (no > 0) + line = mix_vm_cmd_dispatcher_get_src_file_line (vm_dispatcher_, no, FALSE); + + return gh_str02scm ((char *)line); +} + +static SCM +mix_src_line_no_ (void) +{ + return + gh_long2scm (mix_vm_cmd_dispatcher_get_src_file_lineno (vm_dispatcher_)); +} + +/* ----- hook functions ---- */ + +/* auxiliar arg list maker */ +static SCM +make_arg_list_ (const gchar *arg) +{ + gchar **arglist = g_strsplit (arg, " ", -1); + SCM argument = gh_list (SCM_UNDEFINED, SCM_EOL); + if (arglist && arglist[0]) + { + int k = 0; + while (arglist[k]) + argument = gh_cons (gh_str02scm (arglist[k++]), argument); + argument = gh_reverse (argument); + } + g_strfreev (arglist); + return argument; +} + +/* command hook auxiliar functions and types */ +/* +static SCM +hook_error_handler_ (void *data, SCM tag, SCM args){} +*/ +typedef struct +{ + SCM function; + SCM args; +} hook_data_t; + +static SCM +hook_catch_body_ (void *data) +{ + hook_data_t *h = (hook_data_t *)data; + return gh_call1 (h->function, h->args); +} + +static void +scm_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg, gpointer data) +{ + hook_data_t h; + h.function = (SCM) data; + + g_assert (gh_procedure_p (h.function)); + + h.args = make_arg_list_ (arg); + g_assert (gh_list_p (h.args)); + + gh_catch (SCM_BOOL_T, hook_catch_body_, &h, + scm_handle_by_message_noexit, dis); +} + +/* global hook auxiliar functions and types */ +typedef struct +{ + SCM function; + SCM cmd; + SCM args; +} global_hook_data_t; + +static SCM +global_hook_catch_body_ (void *data) +{ + global_hook_data_t *h = (global_hook_data_t *)data; + return gh_call2 (h->function, h->cmd, h->args); +} + +static void +scm_global_hook_ (mix_vm_cmd_dispatcher_t *dis, mix_vm_command_t cmd, + const gchar *arg, gpointer data) +{ + global_hook_data_t h; + h.function = (SCM) data; + h.cmd = gh_str02scm ((char *)mix_vm_command_to_string (cmd)); + h.args = make_arg_list_ (arg); + gh_catch (SCM_BOOL_T, global_hook_catch_body_, &h, + scm_handle_by_message_noexit, NULL); +} + +static SCM +define_hook_procedure_ (SCM function) +{ + enum {BUFF_SIZE = 128}; + static gchar BUFFER[BUFF_SIZE]; + static const gchar *PATTERN = "____mix__hook__%d____"; + static int K = 0; + g_snprintf (BUFFER, BUFF_SIZE, PATTERN, K++); + /* gh_define (name, val) returns a pair: (symbol . symbol-value) */ + return gh_cdr (gh_define ((char *)BUFFER, function)); +} + +static SCM +mix_add_hook_ (SCM cmd, SCM function, gboolean pre) +{ + gchar *cmdstr = NULL; + mix_vm_command_t command; + unsigned int len; + const gchar *fun = pre? "mix-add-pre-hook" : "mix-add-post-hook"; + + SCM_ASSERT (SCM_STRINGP (cmd) || SCM_SYMBOLP (cmd), cmd, SCM_ARG1, fun); + SCM_ASSERT (gh_procedure_p (function), function, SCM_ARG2, fun); + SCM_DEFER_INTS; + cmdstr = gh_scm2newstr (cmd, &len); + command = mix_vm_command_from_string (cmdstr); + g_free (cmdstr); + SCM_ALLOW_INTS; + SCM_ASSERT (command != MIX_CMD_INVALID, cmd, SCM_ARG1, fun); + SCM_DEFER_INTS; + if (pre) + mix_vm_cmd_dispatcher_pre_hook (vm_dispatcher_, command, scm_hook_, + (gpointer) + define_hook_procedure_ (function)); + else + mix_vm_cmd_dispatcher_post_hook (vm_dispatcher_, command, scm_hook_, + (gpointer) + define_hook_procedure_ (function)); + SCM_ALLOW_INTS; + return gh_symbol2scm ("ok"); +} + +static SCM +mix_add_global_hook_ (SCM function, gboolean pre) +{ + const gchar *fun = + pre? "mix-add-global-pre-hook" : "mix-add-global-post-hook"; + + SCM_ASSERT (gh_procedure_p (function), function, SCM_ARG1, fun); + SCM_DEFER_INTS; + if (pre) + mix_vm_cmd_dispatcher_global_pre_hook (vm_dispatcher_, scm_global_hook_, + (gpointer) + define_hook_procedure_ (function)); + else + mix_vm_cmd_dispatcher_global_post_hook (vm_dispatcher_, scm_global_hook_, + (gpointer) + define_hook_procedure_ (function)); + SCM_ALLOW_INTS; + return gh_symbol2scm ("ok"); +} + +static SCM +mix_add_pre_hook_ (SCM cmd, SCM function) +{ + return mix_add_hook_ (cmd, function, TRUE); +} + +static SCM +mix_add_post_hook_ (SCM cmd, SCM function) +{ + return mix_add_hook_ (cmd, function, FALSE); +} + +static SCM +mix_add_global_pre_hook_ (SCM function) +{ + return mix_add_global_hook_ (function, TRUE); +} + +static SCM +mix_add_global_post_hook_ (SCM function) +{ + return mix_add_global_hook_ (function, FALSE); +} + +/* NULL-terminated list of available scm commands */ +const scm_command_t DEFAULT_SCM_COMMANDS_[] = { + {"mixvm-cmd", mixvm_cmd_, 2, 0, 0}, + {"mixvm-status", mixvm_status_, 0, 0, 0}, + {"mix-last-result", mix_last_result_, 0, 0, 0}, + {"mix-reg", mix_reg_, 1, 0, 0}, + {"mix-set-reg!", mix_set_reg_, 2, 0, 0}, + {"mix-cell", mix_cell_, 1, 0, 0}, + {"mix-set-cell!", mix_set_cell_, 2, 0, 0}, + {"mix-over", mix_over_, 0, 0, 0}, + {"mix-loc", mix_loc_, 0, 0, 0}, + {"mix-set-over!", mix_set_over_, 1, 0, 0}, + {"mix-cmp", mix_cmp_, 0, 0, 0}, + {"mix-up-time", mix_uptime_, 0, 0, 0}, + {"mix-lap-time", mix_laptime_, 0, 0, 0}, + {"mix-prog-time", mix_progtime_, 0, 0, 0}, + {"mix-prog-name", mix_prog_name_, 0, 0, 0}, + {"mix-prog-path", mix_prog_path_, 0, 0, 0}, + {"mix-src-name", mix_src_name_, 0, 0, 0}, + {"mix-src-path", mix_src_path_, 0, 0, 0}, + {"mix-src-line-no", mix_src_line_no_, 0, 0, 0}, + {"mix-src-line", mix_src_line_, 0, 1, 0}, + {"mix-ddir", mix_ddir_, 0, 0, 0}, + {"mix-set-cmp!", mix_set_cmp_, 1, 0, 0}, + {"mix-add-pre-hook", mix_add_pre_hook_, 2, 0, 0}, + {"mix-add-post-hook", mix_add_post_hook_, 2, 0, 0}, + {"mix-add-global-pre-hook", mix_add_global_pre_hook_, 1, 0, 0}, + {"mix-add-global-post-hook", mix_add_global_post_hook_, 1, 0, 0}, + {NULL} +}; diff --git a/mixguile/xmixguile_cmd_dispatcher.h b/mixguile/xmixguile_cmd_dispatcher.h new file mode 100644 index 0000000..f7ef756 --- /dev/null +++ b/mixguile/xmixguile_cmd_dispatcher.h @@ -0,0 +1,67 @@ +/* -*-c-*- ---------------- xmixguile_cmd_dispatcher.h : + * Internal declarations for mixguile_cmd_dispatcher_t + * ------------------------------------------------------------------ + * Last change: Time-stamp: <01/08/22 01:11:20 jao> + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef XMIXGUILE_CMD_DISPATCHER_H +#define XMIXGUILE_CMD_DISPATCHER_H + +#include +#include + +#include +#include "mixguile_cmd_dispatcher.h" + +/* the cmd dispatcher type */ +struct mixguile_cmd_dispatcher_t +{ + mix_vm_cmd_dispatcher_t *dispatcher; +}; + +/* scm commands types */ +/* prototype of a function implementing a new scm function */ +typedef SCM (*scm_func_t) (); + +/* record for a new scm command */ +typedef struct scm_command_t +{ + gchar *name; /* name of the scheme command */ + scm_func_t func; /* implementation of the command */ + int argno; /* no. of arguments */ + int opt_argno; /* no. of optional arguments */ + int restp; /* if 1, receive a list of remaining args */ +} scm_command_t; + +/* NULL-terminated list of available scm commands */ +extern const scm_command_t DEFAULT_SCM_COMMANDS_[]; + +/* register a NULL-terminated list of scm commands */ +extern void +register_scm_commands_ (const scm_command_t *commands); + +/* register the mixvm cmd dispatcher to use with commands */ +extern void +register_cmd_dispatcher_ (mixguile_cmd_dispatcher_t *dis); + + +#endif /* XMIXGUILE_CMD_DISPATCHER_H */ + diff --git a/mixlib/Makefile.am b/mixlib/Makefile.am new file mode 100644 index 0000000..b925ff5 --- /dev/null +++ b/mixlib/Makefile.am @@ -0,0 +1,42 @@ +## 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. + +# $Id: Makefile.am,v 1.6 2002/12/08 01:36:49 jao Exp $ + +SUBDIRS = testsuite +INCLUDES = -I$(includedir) -I$(top_srcdir) -DG_LOG_DOMAIN=\"libmix\" + +noinst_LIBRARIES = libmix.a +libmix_a_SOURCES = gettext.h 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 \ + xmix_vm_command.c xmix_vm_command.h \ + xmix_vm_handlers.h xmix_vm_handlers.c \ + mix_config.c mix_config.h \ + mix_predicate.c mix_predicate.h \ + mix_predicate_list.c mix_predicate_list.h + + + + diff --git a/mixlib/gettext.h b/mixlib/gettext.h new file mode 100644 index 0000000..fa3622f --- /dev/null +++ b/mixlib/gettext.h @@ -0,0 +1,69 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# define gettext(Msgid) ((const char *) (Msgid)) +# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +#endif /* _LIBGETTEXT_H */ diff --git a/mixlib/mix.c b/mixlib/mix.c new file mode 100644 index 0000000..3578a57 --- /dev/null +++ b/mixlib/mix.c @@ -0,0 +1,99 @@ +/* -*-c-*- -------------- mix.c : + * Implementation of the functions declared in mix.h + * ------------------------------------------------------------------ + * $Id: mix.c,v 1.6 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include + + +#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) 2001 Free Software Foundation, Inc.\n" +"There is NO warranty. You may redistribute this software\n" +"under the terms of the GNU General Public License.\n" +"For more information about these matters, see the files named COPYING.\n"; + +void +mix_print_license (const gchar *program) +{ + fprintf (stderr, _("%s (GNU MDK %s)\n\n"), + program, VERSION); + fprintf (stderr, MIX_GPL_LICENSE); +} + +/* check dir, and create it if it doesn't exist */ +gboolean +mix_stat_dir (const gchar *dirname, const gchar *alias) +{ + struct stat statbuf; + + g_return_val_if_fail (dirname != NULL, FALSE); + if (alias == NULL) alias = ""; + + if (stat (dirname, &statbuf) == -1) + { + if (errno != ENOENT || mkdir (dirname, S_IRWXU | S_IRWXG | S_IRWXO)) + { + g_warning (_("Error creating %s dir %s: %s"), + alias, dirname, strerror (errno)); + return FALSE; + } + stat (dirname, &statbuf); + } + + if (!(statbuf.st_mode & S_IFDIR)) + { + g_warning (_("Error setting %s dir: %s is not a directory"), + alias, dirname); + return FALSE; + } + + return TRUE; +} diff --git a/mixlib/mix.h b/mixlib/mix.h new file mode 100644 index 0000000..6a3fd1d --- /dev/null +++ b/mixlib/mix.h @@ -0,0 +1,78 @@ +/* -*-c-*- ---------------- mix.h : + * Initialisation of the mix library + * ------------------------------------------------------------------ + * $Id: mix.h,v 1.7 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_H +#define MIX_H + +#ifdef HAVE_CONFIG_H +# include +#else +# warning "config.h not found, package misconfigured." +# define PACKAGE "mdk" +# define VERSION "0.0" +#endif + +#ifdef HAVE_LOCALE_H +# include +#endif + +/* +#ifdef HAVE_GETTEXT +# include +# define gettext_noop(String) (String) +#else +# include +#endif +*/ +#include "gettext.h" + +#define _(String) gettext (String) +#define N_(String) gettext_noop (String) + +#include + +/* 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; + +extern void +mix_print_license (const gchar *program); + + +/* check dir, and create it if it doesn't exist */ +extern gboolean +mix_stat_dir (const gchar *dirname, const gchar *alias); + + +#endif /* MIX_H */ + diff --git a/mixlib/mix_code_file.c b/mixlib/mix_code_file.c new file mode 100644 index 0000000..ab67812 --- /dev/null +++ b/mixlib/mix_code_file.c @@ -0,0 +1,330 @@ +/* -*-c-*- -------------- mix_code_file.c : + * Implementation of the functions declared in mix_code_file.h + * ------------------------------------------------------------------ + * $Id: mix_code_file.c,v 1.6 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2002, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#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->source_path = NULL; + 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) + && (IS_RELEASE_ (result) || IS_DEBUG_ (result)); + + if ( check ) + { + 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) && 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..84b89fb --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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_config.c b/mixlib/mix_config.c new file mode 100644 index 0000000..694b18b --- /dev/null +++ b/mixlib/mix_config.c @@ -0,0 +1,298 @@ +/* -*-c-*- -------------- mix_config.c : + * Implementation of the functions declared in mix_config.h + * ------------------------------------------------------------------ + * $Id: mix_config.c,v 1.12 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +#include +#include +#include +#include +#include "mix_config.h" + +const gchar *MIX_CONFIG_DIR = ".mdk"; + +static const gchar COMMENT_PREFIX_ = '#'; +static const gchar *AUTOSAVE_KEY_ = "Autosave"; +static const gchar *AUTOSAVE_YES_ = "True"; +static const gchar *AUTOSAVE_NO_ = "False"; +static const gchar *DEVICES_KEY_ = "Devices.dir"; +static const gchar *HISTORY_KEY_ = "History.file"; +static const gchar *HISTORY_SIZE_KEY_ = "History.size"; + +/* the config type */ +struct mix_config_t +{ + gchar *filename; /* full path to configuration file */ + gboolean autosave; /* whether save on destroy */ + GHashTable *items; /* configuration items */ +}; + +/* create a new config handler, giving the dir and name of the config file */ +mix_config_t * +mix_config_new (const gchar *dirname, const gchar *filename) +{ + static const gchar *DEF_DIRNAME_ = NULL; + static const gchar *DEF_FILENAME_ = "config"; + + const gchar *autosave; + FILE *f; + mix_config_t *result = NULL; + + if (DEF_DIRNAME_ == NULL) + DEF_DIRNAME_ = g_strconcat (g_get_home_dir (), G_DIR_SEPARATOR_S, + MIX_CONFIG_DIR, NULL); + + if (dirname == NULL) dirname = DEF_DIRNAME_; + if (filename == NULL) filename = DEF_FILENAME_; + + if (!mix_stat_dir (dirname, "configuration")) return NULL; + + result = g_new (mix_config_t, 1); + result->filename = g_strdup_printf ("%s/%s", dirname, filename); + result->items = g_hash_table_new (g_str_hash, g_str_equal); + + f = fopen (result->filename, "r"); + if (f != NULL) + { + enum {LEN = 256}; + gchar buffer[LEN]; + gchar *line = buffer; + while (!feof (f)) + { + line = fgets (line, LEN, f); + if (line) line = g_strstrip (line); + if (line && line[0] != COMMENT_PREFIX_) + { + gchar **vals = g_strsplit (line, "=", 2); + g_hash_table_insert (result->items, + (gpointer) g_strstrip (vals[0]), + (gpointer) g_strstrip (vals[1])); + } + } + fclose (f); + } + + autosave = mix_config_get (result, AUTOSAVE_KEY_); + result->autosave = autosave && !g_ascii_strcasecmp (autosave, AUTOSAVE_YES_); + + return result; +} + +/* delete a config handler, saving the configuration if needed */ +void +mix_config_delete (mix_config_t *config) +{ + g_return_if_fail (config != NULL); + if (mix_config_is_autosave (config)) mix_config_save (config); + g_free (config->filename); + g_hash_table_destroy (config->items); + g_free (config); +} + +/* get the config filename */ +const gchar * +mix_config_get_filename (const mix_config_t *config) +{ + g_return_val_if_fail (config != NULL, NULL); + return config->filename; +} + +/* get a config item's value from its key */ +const gchar * +mix_config_get (const mix_config_t *config, const gchar *key) +{ + g_return_val_if_fail (config != NULL, NULL); + g_return_val_if_fail (key != NULL, NULL); + + return (const gchar*)g_hash_table_lookup (config->items, key); +} + +gint +mix_config_get_integer (const mix_config_t *config, const gchar *key) +{ + const gchar *val; + g_return_val_if_fail (config != NULL, 0); + g_return_val_if_fail (key != NULL, 0); + val = mix_config_get (config, key); + if (!val) return 0; + return atoi (val); +} + +/* update (or create if it does not exist) a new config item */ +void +mix_config_update (mix_config_t *config, const gchar *key, const gchar *value) +{ + gpointer okey = NULL; + gpointer oval = NULL; + + g_return_if_fail (config != NULL); + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + if (g_hash_table_lookup_extended (config->items, key, &okey, &oval)) + { + if (oval != value) + { + g_free (oval); + oval = (gpointer)g_strdup (value); + } + } + else + { + okey = (gpointer)g_strdup (key); + oval = (gpointer)g_strdup (value); + } + + g_hash_table_insert (config->items, okey, oval); +} + +void +mix_config_update_integer (mix_config_t *config, const gchar *key, gint value) +{ + gchar *val; + + g_return_if_fail (config != NULL); + g_return_if_fail (key != NULL); + + val = g_strdup_printf ("%d", value); + mix_config_update (config, key, val); + g_free (val); +} + +void +mix_config_remove (mix_config_t *config, const gchar *key) +{ + gchar *val; + + g_return_if_fail (config != NULL); + g_return_if_fail (key != NULL); + + val = g_hash_table_lookup (config->items, key); + if (val != NULL) + { + g_hash_table_remove (config->items, key); + g_free (val); + } +} + +/* save the current configuration */ +static void +save_ (gpointer key, gpointer value, gpointer file) +{ + fprintf ((FILE *)file, "%s=%s\n", (char *)key, (char *)value); +} + +void +mix_config_save (const mix_config_t *config) +{ + FILE *f; + + g_return_if_fail (config != NULL); + + f = fopen (config->filename, "w"); + if (!f) + { + g_warning (_("Unable to open config file %s (%s)"), + config->filename, g_strerror (errno)); + return; + } + g_hash_table_foreach (config->items, save_, (gpointer)f); + fclose (f); +} + +/* set autosave on delete flag */ +void +mix_config_set_autosave (mix_config_t *config, gboolean autosave) +{ + mix_config_update (config, AUTOSAVE_KEY_, + autosave? AUTOSAVE_YES_ : AUTOSAVE_NO_); + config->autosave = autosave; +} + + +gboolean +mix_config_is_autosave (const mix_config_t *config) +{ + g_return_val_if_fail (config != NULL, FALSE); + return config->autosave; +} + +/* devices dir*/ +void +mix_config_set_devices_dir (mix_config_t *config, const gchar *dirname) +{ + g_return_if_fail (config != NULL); + g_return_if_fail (dirname != NULL); + if (mix_stat_dir (dirname, "devices")) + mix_config_update (config, DEVICES_KEY_, dirname); +} + +extern const gchar * +mix_config_get_devices_dir (const mix_config_t *config) +{ + g_return_val_if_fail (config != NULL, NULL); + return mix_config_get (config, DEVICES_KEY_); +} + +/* history file. if relative path, config dir taken as root */ +void +mix_config_set_history_file (mix_config_t *config, const gchar *path) +{ + g_return_if_fail (config != NULL); + g_return_if_fail (path != NULL); + if (g_path_is_absolute (path)) + { + mix_config_update (config, HISTORY_KEY_, path); + } + else + { + gchar *base = g_path_get_dirname (config->filename); + gchar *hf = g_strconcat (base, G_DIR_SEPARATOR_S, path, NULL); + mix_config_update (config, HISTORY_KEY_, hf); + g_free (hf); + g_free (base); + } +} + +const gchar * +mix_config_get_history_file (const mix_config_t *config) +{ + g_return_val_if_fail (config != NULL, NULL); + return mix_config_get (config, HISTORY_KEY_); +} + +void +mix_config_set_history_size (mix_config_t *config, gint s) +{ + g_return_if_fail (config != NULL); + g_return_if_fail (s >= 0); + mix_config_update_integer (config, HISTORY_SIZE_KEY_, s); +} + +gint +mix_config_get_history_size (const mix_config_t *config) +{ + g_return_val_if_fail (config != NULL, 0); + return mix_config_get_integer (config, HISTORY_SIZE_KEY_); +} diff --git a/mixlib/mix_config.h b/mixlib/mix_config.h new file mode 100644 index 0000000..9d2af32 --- /dev/null +++ b/mixlib/mix_config.h @@ -0,0 +1,100 @@ +/* -*-c-*- ---------------- mix_config.h : + * Basic config storage utility. + * ------------------------------------------------------------------ + * $Id: mix_config.h,v 1.6 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_CONFIG_H +#define MIX_CONFIG_H + +#include "mix.h" + +/* default config dir */ +extern const gchar *MIX_CONFIG_DIR; + +/* the config type */ +typedef struct mix_config_t mix_config_t; + +/* create a new config handler, giving the dir and name of the config file */ +extern mix_config_t * +mix_config_new (const gchar *dirname, const gchar *filename); + +/* delete a config handler, saving the configuration if needed */ +extern void +mix_config_delete (mix_config_t *config); + +/* get the config filename (fully qualified) */ +extern const gchar * +mix_config_get_filename (const mix_config_t *config); + +/* get a config item's value from its key */ +extern const gchar * +mix_config_get (const mix_config_t *config, const gchar *key); + +extern gint +mix_config_get_integer (const mix_config_t *config, const gchar *key); + +/* update (or create if it does not exist) a new config item */ +extern void +mix_config_update (mix_config_t *config, const gchar *key, const gchar *value); + +extern void +mix_config_update_integer (mix_config_t *config, const gchar *key, gint value); + +extern void +mix_config_remove (mix_config_t *config, const gchar *key); + +/* save the current configuration */ +extern void +mix_config_save (const mix_config_t *config); + +/** shared config params **/ + +/* set autosave on delete flag */ +extern void +mix_config_set_autosave (mix_config_t *config, gboolean autosave); + +extern gboolean +mix_config_is_autosave (const mix_config_t *config); + +/* devices dir*/ +extern void +mix_config_set_devices_dir (mix_config_t *config, const gchar *dirname); + +extern const gchar * +mix_config_get_devices_dir (const mix_config_t *config); + +/* history file. if relative path, config dir taken as root */ +extern void +mix_config_set_history_file (mix_config_t *config, const gchar *path); + +extern const gchar * +mix_config_get_history_file (const mix_config_t *config); + +extern void +mix_config_set_history_size (mix_config_t *config, gint s); + +extern gint +mix_config_get_history_size (const mix_config_t *config); + + +#endif /* MIX_CONFIG_H */ + diff --git a/mixlib/mix_device.c b/mixlib/mix_device.c new file mode 100644 index 0000000..6a99e8a --- /dev/null +++ b/mixlib/mix_device.c @@ -0,0 +1,164 @@ +/* -*-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mix_file.h" +#include "xmix_device.h" + +/* + Set the directory for mix device files (by default, it's ".") + If the dir does not exist, it is created. +*/ +gboolean +mix_device_set_dir (const gchar *dirname) +{ + if (mix_stat_dir (dirname, "devices")) + { + if (DEV_DIR_) g_free (DEV_DIR_); + DEV_DIR_ = g_strdup (dirname); + return TRUE; + } + else + return FALSE; +} + +const gchar * +mix_device_get_dir (void) +{ + return DEV_DIR_; +} + +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); + construct_device_ (result, type); + 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); + construct_device_with_name_ (result, type, name); + 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); + construct_device_with_file_ (result, type, file); + return result; +} + +void +mix_device_delete (mix_device_t *dev) +{ + if (dev != NULL) + { + (dev->vtable->destroy) (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..7830dfe --- /dev/null +++ b/mixlib/mix_device.h @@ -0,0 +1,160 @@ +/* -*-c-*- ---------------- mix_device.h : + * Declaration of mix_device_t and associated methods. + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_DEVICE_H +#define MIX_DEVICE_H + +#include +#include +#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; + +/* + Set the directory for mix device files (by default, it's ".") + If the dir does not exist, it is created. +*/ +extern gboolean +mix_device_set_dir (const gchar *dirname); + +extern const gchar * +mix_device_get_dir (void); + +/* + 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..f6f816a --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..c1c1243 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..8d0d3bd --- /dev/null +++ b/mixlib/mix_eval_scanner.l @@ -0,0 +1,276 @@ +/* -*-c-*- ------------------ mix_eval_scanner.l : + * scanner used by mix_eval_t + * ------------------------------------------------------------------ + * $Id: mix_eval_scanner.l,v 1.4 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +%{ +#include +#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); + +/* { */ +/* 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; */ +/* } */ + +%} + +%option nomain +%option caseless +%option array +%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; +%} + + +<*><> { + CLEAN_UP (); + return MIX_EVAL_INTERN; +} + +{ + {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; + } +} + +{ + {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); +} + +{ + {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..383d3b4 --- /dev/null +++ b/mixlib/mix_file.c @@ -0,0 +1,159 @@ +/* -*-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#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; + const gchar *fmode = fmode_to_type_ (mode); + + /* if the read/write file already exists, open in r+ mode */ + if (mode == mix_io_RDWRT && (file = fopen (name, "r"))) + { + fmode = "r+"; + fclose (file); + } + + result = g_new(mix_file_t, 1); + file = fopen(name, fmode); + 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); +} + +/* complete a name with an extension, if needed */ +gchar * +mix_file_complete_name (const gchar *name, const gchar *extension) +{ + if (!name) return NULL; + if (!extension || !needs_completion_ (name, extension)) + return g_strdup (name); + return add_completion_ (name, extension); +} + +/* 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..059eebb --- /dev/null +++ b/mixlib/mix_file.h @@ -0,0 +1,65 @@ +/* -*-c-*- ---------------- mix_file.h : + * Declarations for the mix_file_t type. + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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; + +/* complete a name with an extension, if needed */ +extern gchar * +mix_file_complete_name (const gchar *name, const gchar *extension); + +/* 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..1aa3f70 --- /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, 2003 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..07d8e38 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..31e43df --- /dev/null +++ b/mixlib/mix_io.c @@ -0,0 +1,208 @@ +/* -*-c-*- --------------- mix_io.c : + * Implementation of the functions declared in mix_io.h + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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) +{ + if (ioc == NULL) return NULL; + return ioc->file; +} + +gboolean +mix_io_eof (mix_iochannel_t *ioc) +{ + if (ioc == NULL) return TRUE; + return is_eof_ (ioc); +} + +gboolean +mix_io_is_ready (mix_iochannel_t *ioc) +{ + if (ioc == NULL) return FALSE; + return is_ready_ (ioc); +} + +gboolean +mix_io_write_byte (mix_iochannel_t *ioc, mix_byte_t b) +{ + if (ioc == NULL) return 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) +{ + if (ioc == NULL || b == NULL) return 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; + if (ioc != NULL) read_data_ (ioc, &result, 1); + return result; +} + +gboolean +mix_io_read_byte_array (mix_iochannel_t *ioc, mix_byte_t *b, size_t s) +{ + return (ioc != NULL) && (b != NULL) && read_data_ (ioc, b, s); +} + +gboolean +mix_io_write_word (mix_iochannel_t *ioc, mix_word_t w) +{ + return (ioc != NULL) && write_data_ (ioc, &w, 1); +} + +gboolean +mix_io_write_word_array (mix_iochannel_t *ioc, const mix_word_t *w, + size_t s) +{ + return (ioc != NULL) && (w != NULL) && write_data_ (ioc, w, s); +} + +mix_word_t +mix_io_read_word (mix_iochannel_t *ioc) +{ + mix_word_t result = MIX_WORD_ZERO; + if (ioc != NULL) read_data_ (ioc, &result, 1); + return result; +} + +gboolean +mix_io_read_word_array (mix_iochannel_t *ioc, mix_word_t *w, size_t s) +{ + return (ioc != NULL) && (w != NULL) && read_data_ (ioc, w, s); +} + +gboolean +mix_io_write_short (mix_iochannel_t *ioc, mix_short_t w) +{ + return (ioc != NULL) && write_data_ (ioc, &w, 1); +} + +gboolean +mix_io_write_short_array (mix_iochannel_t *ioc, const mix_short_t *w, + size_t s) +{ + return (ioc != NULL) && (w != NULL) && write_data_ (ioc, w, s); +} + +mix_short_t +mix_io_read_short (mix_iochannel_t *ioc) +{ + mix_short_t result = MIX_SHORT_ZERO; + if (ioc != NULL) read_data_ (ioc, &result, 1); + return result; +} + +gboolean +mix_io_read_short_array (mix_iochannel_t *ioc, mix_short_t *w, size_t s) +{ + return (ioc != NULL) && (w != NULL) && 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); + return (ioc != NULL) && write_data_ (ioc, &value, 1); +} + +mix_char_t +mix_io_read_char (mix_iochannel_t *ioc) +{ + guchar value = MIX_CHAR_MAX; + if (ioc != NULL) read_data_ (ioc, &value, 1); + 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; + guchar value; + + if ((ioc == NULL) || (w == NULL)) return FALSE; + + for (k = 0; k < s; k++) + for (j = 1; j < 6; j++) + { + mix_char_t ch = mix_byte_to_char (mix_word_get_byte (w[k], j)); + value = mix_char_to_ascii (ch); + if (!write_data_ (ioc, &value, 1)) return FALSE; + } + value = '\n'; + return write_data_ (ioc, &value, 1); +} + +gboolean +mix_io_read_word_array_as_char (mix_iochannel_t *ioc, + mix_word_t *w, size_t s) +{ + guint k, j; + guchar value; + gboolean eol = FALSE; + mix_char_t spc = mix_ascii_to_char (' '); + + if ((ioc == NULL) || (w == NULL)) return FALSE; + + for (k = 0; k < s && !eol; k++) + for (j = 1; j < 6; j++) + { + if (!eol && !read_data_ (ioc, &value, 1)) return FALSE; + eol = eol || (value == '\n') || is_eof_ (ioc); + mix_word_set_byte (&w[k], j, eol? spc : mix_ascii_to_char (value)); + } + for (; k < s; ++k) w[k] = MIX_WORD_ZERO; + + while (!eol && !is_eof_ (ioc) && value != '\n') + if (!read_data_ (ioc, &value, 1)) return FALSE; + + return TRUE; +} diff --git a/mixlib/mix_io.h b/mixlib/mix_io.h new file mode 100644 index 0000000..0e79d67 --- /dev/null +++ b/mixlib/mix_io.h @@ -0,0 +1,119 @@ +/* -*-c-*- ------------------ mix_io.h : + * Declarations for mix_iochannel_t and mix_file_t + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_IOCHANNEL_H +#define MIX_IOCHANNEL_H + +#include +#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..0dfcf81 --- /dev/null +++ b/mixlib/mix_parser.c @@ -0,0 +1,605 @@ +/* -*-c-*- -------------- mix_parser.c : + * Implementation of the functions declared in mix_parser.h and + * xmix_parser.h + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include "mix.h" +#include "mix_code_file.h" +#include "xmix_parser.h" + +/* The flex-generated scanner, according to file mix_scanner.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"), + N_("operand of ALF pseudo instruction must be quoted") +}; + +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->con_list = NULL; + result->alf_list = NULL; + result->in_file = f; + result->loc_count = MIX_SHORT_ZERO; + result->start = MIX_SHORT_ZERO; + result->end = 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_foreach (parser->ins_table, delete_tree_vals_, 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); + g_slist_free (parser->con_list); + g_slist_free (parser->alf_list); + mix_file_delete (parser->in_file); + g_free (parser); +} + +/* Compile a mix source file */ +static void +update_future_refs_value_ (mix_parser_t *parser, const gchar *name, + mix_short_t value, gboolean remove) +{ + GSList *list = NULL; + gpointer *plist = (gpointer *)(&list); + gpointer key; + + g_assert (parser != NULL && name != NULL); + if ( g_hash_table_lookup_extended (parser->future_refs, name, &key, plist) ) + { + 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); + } + if (remove) { + g_hash_table_remove (parser->future_refs, name); + g_free (key); + } + g_slist_free (list); + } +} + +#define update_future_refs_(parser,name,rem) \ + update_future_refs_value_(parser, name, (parser)->loc_count, rem) + +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); + update_future_refs_ (par, (const gchar *)symbol, TRUE); + mix_parser_add_ins (par, &ins, 0); + par->loc_count++; +} + +static gboolean +undef_warning_ (gpointer symbol, gpointer value, gpointer data) +{ + mix_parser_t *parser = (mix_parser_t *)data; + const gchar *name = (const gchar *)symbol; + mix_ins_t ins; + + mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, 0, name, TRUE); + + mix_word_to_ins_uncheck (MIX_WORD_ZERO, ins); + update_future_refs_ (parser, name, FALSE); + mix_parser_add_ins (parser, &ins, 0); + mix_symbol_table_insert (parser->symbol_table, name, + mix_short_to_word_fast (parser->loc_count)); + + parser->loc_count++; + return TRUE; +} + +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 ) + { + parser->loc_count = parser->end; + mix_symbol_table_foreach (parser->ls_table, update_ls_, (gpointer)parser); + if ( g_hash_table_size (parser->future_refs) > 0) + { + 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 *source_path; + + g_return_val_if_fail (parser != NULL, MIX_PERR_INTERNAL); + if (parser->status != MIX_PERR_OK ) return parser->status; + context.parser = parser; + if (!g_path_is_absolute (mix_file_base_name (parser->in_file))) + { + gchar *dir = g_get_current_dir (); + source_path = g_strconcat (dir, G_DIR_SEPARATOR_S, + mix_file_base_name (parser->in_file), NULL); + g_free (dir); + } + else + source_path = g_strdup (mix_file_base_name (parser->in_file)); + + context.file = mix_code_file_new_write (cfname, parser->start, source_path, + debug, parser->symbol_table); + g_free (source_path); + + if (context.file == NULL) return MIX_PERR_NOOUT; + g_tree_foreach (parser->ins_table, write_code_, (gpointer)&context); + mix_code_file_delete (context.file); + return parser->status; +} + +/* Produce a listing file summarising the compilation */ +typedef struct +{ + FILE *file; + mix_parser_t *parser; +} listing_context_t; + +static gint +write_listing_ (gpointer address, gpointer ins, gpointer context) +{ + guint k; + FILE *file = ((listing_context_t *)context)->file; + mix_parser_t *parser = ((listing_context_t *)context)->parser; + guint end = parser->end; + ins_node_ *ins_node = (ins_node_ *)ins; + mix_ins_t instruct; + + fprintf (file, "%03d %05d %s ", + ins_node->lineno, + 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)); + + if (g_slist_find (parser->con_list, GUINT_TO_POINTER (ins_node->lineno)) + || GPOINTER_TO_UINT (address) >= end) + fprintf (file, "\tCON\t%04d\n", (int)(ins_node->ins)); + else if (g_slist_find (parser->alf_list, GUINT_TO_POINTER (ins_node->lineno))) + { + size_t i; + fprintf (file, "\tALF\t\""); + for (i = 1; i < 6; ++i) + fprintf (file, "%c", + mix_char_to_ascii (mix_byte_to_char + (mix_word_get_byte (ins_node->ins, i)))); + fprintf (file, "\"\n"); + } + else if (GPOINTER_TO_UINT (address) < end) + { + 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, _("\t%s\n"), instext? instext : _("UNKNOWN")); + if (instext) g_free (instext); + } + else + g_assert_not_reached (); + + return FALSE; +} + +mix_parser_err_t +mix_parser_write_listing (mix_parser_t *parser, const gchar *list_file) +{ + mix_file_t *mfile; + const gchar *name; + listing_context_t context; + static const char *sep = + "-----------------------------------------------------------------\n"; + + 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; + context.file = mix_file_to_FILE (mfile); + context.parser = parser; + fprintf (context.file, _("*** %s%s: compilation summary ***\n\n"), + mix_file_base_name (parser->in_file), + mix_file_extension (parser->in_file)); + fputs (sep, context.file); + fputs ( _("Src Address Compiled word Symbolic rep\n"), + context.file); + fputs (sep, context.file); + g_tree_foreach (parser->ins_table, write_listing_, (gpointer)(&context)); + fputs (sep, context.file); + fprintf (context.file, _("\n*** Start address:\t%d\n*** End address:\t%d\n"), + mix_short_magnitude (parser->start), + mix_short_magnitude (parser->end)); + fprintf (context.file, _("\n*** Symbol table\n")); + mix_symbol_table_print (parser->symbol_table, MIX_SYM_ROWS, + context.file, TRUE); + fprintf (context.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_foreach (parser->ins_table, load_vm_, (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, TRUE); + 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, TRUE); + 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 */ +static void +add_raw_ (mix_parser_t *parser, mix_word_t word, guint lineno) +{ + 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); + } +} + +void +mix_parser_add_ins (mix_parser_t *parser, const mix_ins_t *new_ins, + guint lineno) +{ + g_assert (parser != NULL && new_ins != NULL); + 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, + gboolean is_con) +{ + g_assert (parser != NULL); + add_raw_ (parser, word, lineno); + if ( parser->status == MIX_PERR_NOCOMP || parser->status == MIX_PERR_OK ) + { + if (is_con) + parser->con_list = g_slist_append (parser->con_list, + GUINT_TO_POINTER (lineno)); + else + parser->alf_list = g_slist_append (parser->alf_list, + GUINT_TO_POINTER (lineno)); + } +} + +/* 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..2335fb1 --- /dev/null +++ b/mixlib/mix_parser.h @@ -0,0 +1,111 @@ +/* -*-c-*- ---------------- mix_parser.h : + * Declarations for mix_parser_t, which compiles a source file into + * a mix code file. + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_PARSER_H +#define MIX_PARSER_H + +#include +#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_PERR_UNQUOTED_ALF /* unquoted 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_predicate.c b/mixlib/mix_predicate.c new file mode 100644 index 0000000..2143757 --- /dev/null +++ b/mixlib/mix_predicate.c @@ -0,0 +1,215 @@ +/* -*-c-*- -------------- mix_predicate.c : + * Implementation of the functions declared in mix_predicate.h + * ------------------------------------------------------------------ + * $Id: mix_predicate.c,v 1.6 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mix_vm.h" +#include "mix_predicate.h" + +/* predicate data */ +typedef union pred_data_t +{ + mix_word_t regA; + mix_word_t regX; + mix_short_t regI; + mix_cmpflag_t cmp; + gboolean over; + mix_word_t mem; +} pred_data_t; + +/* the predicate function type */ +typedef gboolean (*mix_predicate_fun_t) (mix_predicate_t *pred, + const mix_vm_t *vm); + +/* the predicate type */ +struct mix_predicate_t +{ + mix_predicate_type_t type; + pred_data_t data; + guint control; +}; + +/* predicate funcs */ +static gboolean +pred_func_rA (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_word_t val = mix_vm_get_rA (vm); + if (pred->data.regA == val) return FALSE; + pred->data.regA = val; + return TRUE; +} + +static gboolean +pred_func_rX (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_word_t val = mix_vm_get_rX (vm); + if (pred->data.regX == val) return FALSE; + pred->data.regX = val; + return TRUE; +} + +static gboolean +pred_func_rI (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_short_t val = (pred->control == 0) ? mix_vm_get_rJ (vm) + : mix_vm_get_rI (vm, pred->control); + if (pred->data.regI == val) return FALSE; + pred->data.regI = val; + return TRUE; +} + +static gboolean +pred_func_mem (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_word_t val = + mix_vm_get_addr_contents (vm, (mix_address_t)pred->control); + if (pred->data.mem == val) return FALSE; + pred->data.mem = val; + return TRUE; +} + +static gboolean +pred_func_cmp (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_cmpflag_t val = mix_vm_get_cmpflag (vm); + if (pred->data.cmp == val) return FALSE; + pred->data.cmp = val; + return TRUE; +} + +static gboolean +pred_func_over (mix_predicate_t *pred, const mix_vm_t *vm) +{ + gboolean val = mix_vm_get_overflow (vm); + if (pred->data.over == val) return FALSE; + pred->data.over = val; + return TRUE; +} + +static mix_predicate_fun_t PRED_FUNCS_[] = { + pred_func_rA, pred_func_rX, pred_func_rI, pred_func_rI, pred_func_rI, + pred_func_rI, pred_func_rI, pred_func_rI, pred_func_rI, + pred_func_over, pred_func_cmp, pred_func_mem +}; + +/* create predicates based on vm status */ +mix_predicate_t * +mix_predicate_new (mix_predicate_type_t type) +{ + mix_predicate_t *result; + g_return_val_if_fail (type <= MIX_PRED_MEM, NULL); + result = g_new (mix_predicate_t, 1); + result->type = type; + result->data.regA = MIX_WORD_ZERO; + if (type >= MIX_PRED_REG_I1 && type <= MIX_PRED_REG_I6) + result->control = 1 + type - MIX_PRED_REG_I1; + else + result->control = 0; + return result; +} + +/* delete a predicate */ +void +mix_predicate_delete (mix_predicate_t *predicate) +{ + g_return_if_fail (predicate != NULL); + g_free (predicate); +} + +/* return the predicate's type */ +mix_predicate_type_t +mix_predicate_get_type (const mix_predicate_t *pred) +{ + g_return_val_if_fail (pred != NULL, MIX_PRED_INVALID); + return pred->type; +} + +/* test a predicate */ +gboolean +mix_predicate_eval(mix_predicate_t *pred, const mix_vm_t *vm) +{ + g_return_val_if_fail (pred != NULL, FALSE); + g_return_val_if_fail (vm != NULL, FALSE); + return PRED_FUNCS_[pred->type] (pred, vm); +} + +/* change mem address of a MIX_PRED_MEM predicate */ +void +mix_predicate_set_mem_address (mix_predicate_t *predicate, + mix_address_t address) +{ + g_return_if_fail (predicate != NULL); + predicate->control = address; +} + +/* get message about predicate evaluation */ +const gchar * +mix_predicate_get_message (const mix_predicate_t *predicate) +{ + enum {SIZE = 256}; + static gchar BUFFER[SIZE]; + static const gchar *CMP_STRINGS[] = { "L", "E", "G"}; + + g_return_val_if_fail (predicate != NULL, NULL); + + switch (predicate->type) + { + case MIX_PRED_REG_A: + g_snprintf (BUFFER, SIZE, _("Register A changed to %s%ld"), + mix_word_is_negative (predicate->data.regA)? "-" : "+", + mix_word_magnitude (predicate->data.regA)); + break; + case MIX_PRED_REG_X: + g_snprintf (BUFFER, SIZE, _("Register X changed to %s%ld"), + mix_word_is_negative (predicate->data.regX)? "-" : "+", + mix_word_magnitude (predicate->data.regX)); + break; + case MIX_PRED_REG_J: + g_snprintf (BUFFER, SIZE, _("Register J changed to %d"), + mix_short_magnitude (predicate->data.regI)); + break; + case MIX_PRED_REG_I1: case MIX_PRED_REG_I2: case MIX_PRED_REG_I3: + case MIX_PRED_REG_I4: case MIX_PRED_REG_I5: case MIX_PRED_REG_I6: + g_snprintf (BUFFER, SIZE, _("Register I%d changed to %s%d"), + predicate->control, + mix_short_is_negative (predicate->data.regI)? "-" : "+", + mix_short_magnitude (predicate->data.regI)); + break; + case MIX_PRED_CMP: + g_snprintf (BUFFER, SIZE, _("Comparison flag changed to %s"), + CMP_STRINGS[predicate->data.cmp]); + break; + case MIX_PRED_OVER: + g_snprintf (BUFFER, SIZE, _("Overflow toggled %s"), + predicate->data.over ? "ON" : "OFF"); + break; + case MIX_PRED_MEM: + g_snprintf (BUFFER, SIZE, _("Memory address %d changed to %s%ld"), + predicate->control, + mix_word_is_negative (predicate->data.mem)? "-" : "+", + mix_word_magnitude (predicate->data.mem)); + break; + default: + g_assert_not_reached (); + } + return BUFFER; +} + diff --git a/mixlib/mix_predicate.h b/mixlib/mix_predicate.h new file mode 100644 index 0000000..903de57 --- /dev/null +++ b/mixlib/mix_predicate.h @@ -0,0 +1,80 @@ +/* -*-c-*- ---------------- mix_predicate.h : + * Predicates and lists of predicates testing vm status. + * ------------------------------------------------------------------ + * Last change: Time-stamp: <2001-07-13 22:32:42 jao> + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_PREDICATE_H +#define MIX_PREDICATE_H + +#include "mix.h" +#include "mix_types.h" +#include "mix_ins.h" + +/* the predicate type */ +typedef struct mix_predicate_t mix_predicate_t; + +/* predicate types */ +typedef enum { + MIX_PRED_REG_A, + MIX_PRED_REG_X, + MIX_PRED_REG_J, + MIX_PRED_REG_I1, + MIX_PRED_REG_I2, + MIX_PRED_REG_I3, + MIX_PRED_REG_I4, + MIX_PRED_REG_I5, + MIX_PRED_REG_I6, + MIX_PRED_OVER, + MIX_PRED_CMP, + MIX_PRED_MEM, + MIX_PRED_INVALID +} mix_predicate_type_t; + +/* create predicates based on vm status */ +extern mix_predicate_t * +mix_predicate_new (mix_predicate_type_t type); + +/* delete a predicate */ +extern void +mix_predicate_delete (mix_predicate_t *predicate); + +/* return the predicate's type */ +extern mix_predicate_type_t +mix_predicate_get_type (const mix_predicate_t *pred); + +/* change mem address of a MIX_PRED_MEM predicate */ +extern void +mix_predicate_set_mem_address (mix_predicate_t *predicate, + mix_address_t address); + +/* get message about predicate evaluation */ +extern const gchar * +mix_predicate_get_message (const mix_predicate_t *predicate); + +/* test a predicate */ +#include "mix_vm.h" + +extern gboolean +mix_predicate_eval(mix_predicate_t *pred, const mix_vm_t *vm); + +#endif /* MIX_PREDICATE_H */ + diff --git a/mixlib/mix_predicate_list.c b/mixlib/mix_predicate_list.c new file mode 100644 index 0000000..1b68d35 --- /dev/null +++ b/mixlib/mix_predicate_list.c @@ -0,0 +1,117 @@ +/* -*-c-*- -------------- mix_predicate_list.c : + * Implementation of the functions declared in mix_predicate_list.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "01/07/18 23:02:26 jao" + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "mix_predicate_list.h" + +/* the predicate list type */ +struct mix_predicate_list_t +{ + GSList *predicates; + const mix_vm_t *vm; + const mix_predicate_t *last; +}; + +/* a list of predicates */ +mix_predicate_list_t * +mix_predicate_list_new (const mix_vm_t *vm) +{ + mix_predicate_list_t *result; + g_return_val_if_fail (vm != NULL, NULL); + result = g_new (mix_predicate_list_t, 1); + result->predicates = NULL; + result->vm = vm; + result->last = NULL; + return result; +} + +void +mix_predicate_list_delete (mix_predicate_list_t *list) +{ + g_return_if_fail (list != NULL); + g_slist_free (list->predicates); + g_free (list); +} + +/* evaluate the predicate list */ +gboolean +mix_predicate_list_eval (mix_predicate_list_t *list) +{ + GSList *node; + + g_return_val_if_fail (list != NULL, FALSE); + node = list->predicates; + while (node) { + mix_predicate_t *pred = (mix_predicate_t *)(node->data); + if (mix_predicate_eval (pred, list->vm)) + { + list->last = pred; + return TRUE; + } + node = node->next; + } + list->last = NULL; + return FALSE; +} + +/* add/remove predicates to the list */ +void +mix_predicate_list_add (mix_predicate_list_t *list, mix_predicate_t *predicate) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (predicate != NULL); + if (!g_slist_find (list->predicates, predicate)) + list->predicates = g_slist_append (list->predicates, (gpointer)predicate); + (void)mix_predicate_eval (predicate, list->vm); +} + +gboolean +mix_predicate_list_remove (mix_predicate_list_t *list, + mix_predicate_t *predicate) +{ + g_return_val_if_fail (list != NULL, FALSE); + g_return_val_if_fail (predicate != NULL, FALSE); + if (g_slist_find (list->predicates, predicate)) + { + list->predicates = g_slist_remove (list->predicates, predicate); + return TRUE; + } + else + return FALSE; +} + +void +mix_predicate_list_clear (mix_predicate_list_t *list) +{ + g_return_if_fail (list != NULL); + g_slist_free (list->predicates); + list->predicates = NULL; + list->last = NULL; +} + +const mix_predicate_t * +mix_predicate_list_last_true_eval (const mix_predicate_list_t *list) +{ + g_return_val_if_fail (list != NULL, NULL); + return list->last; +} diff --git a/mixlib/mix_predicate_list.h b/mixlib/mix_predicate_list.h new file mode 100644 index 0000000..d651df7 --- /dev/null +++ b/mixlib/mix_predicate_list.h @@ -0,0 +1,64 @@ +/* -*-c-*- ---------------- mix_predicate_list.h : + * A list of predicates. + * ------------------------------------------------------------------ + * Last change: Time-stamp: <01/07/18 23:02:40 jao> + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_PREDICATE_LIST_H +#define MIX_PREDICATE_LIST_H + +#include "mix.h" +#include "mix_vm.h" +#include "mix_predicate.h" + +/* the predicate list type */ +typedef struct mix_predicate_list_t mix_predicate_list_t; + +/* create/destroy a list of predicates */ +extern mix_predicate_list_t * +mix_predicate_list_new (const mix_vm_t *vm); + +extern void +mix_predicate_list_delete (mix_predicate_list_t *list); + +/* evaluate the predicate list */ +extern gboolean +mix_predicate_list_eval (mix_predicate_list_t *list); + +extern const mix_predicate_t * +mix_predicate_list_last_true_eval (const mix_predicate_list_t *list); + +#define mix_predicate_list_last_true_eval_type(list) \ + mix_predicate_get_type (mix_predicate_list_last_true_eval (list)) + +/* add/remove predicates to the list */ +extern void +mix_predicate_list_add (mix_predicate_list_t *list, mix_predicate_t *predicate); + +extern gboolean +mix_predicate_list_remove (mix_predicate_list_t *list, + mix_predicate_t *predicate); + +extern void +mix_predicate_list_clear (mix_predicate_list_t *list); + +#endif /* MIX_PREDICATE_LIST_H */ + diff --git a/mixlib/mix_scanner.l b/mixlib/mix_scanner.l new file mode 100644 index 0000000..6150007 --- /dev/null +++ b/mixlib/mix_scanner.l @@ -0,0 +1,581 @@ +/* -*-c-*- -------------- mix_scanner.l : + * Lexical scanner used by mix_parser_t + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +%{ +#include +#include + +#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,is_con) \ + do { \ + mix_parser_add_raw (parser, value, lineno, is_con); \ + 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(s) \ + do { \ + wexpr_val = MIX_WORD_ZERO; \ + wexpr_val_tmp = MIX_WORD_ZERO; \ + is_fp = FALSE; \ + yyless (s); \ + 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 array +%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; +#ifdef FLEX_DEBUG + yy_flex_debug = getenv("FLEX_DEBUG"); +#endif + yyin = mix_file_to_FILE (parser->in_file); + +%} + + +<*><> { + mix_parser_log_error (parser, MIX_PERR_UNEX_EOF, lineno, NULL, FALSE); + return MIX_PERR_UNEX_EOF; +} + +{ + ^\*.* /* eat comments */ + . { + if ( end ) return parser->status; + yyless (0); + BEGIN (LOC); + } + \n { + ++lineno; + if ( end ) return parser->status; + } +} + +{ + {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 */ +} + +{ + {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}{0,5}\"{ws}+.*\n | + ALF{ws}+\"{mixchar}{0,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); + /* Fill with spaces */ + for (; k < 5+j; k++) + bytes[k-j] = mix_ascii_to_char (' '); + } + 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, FALSE); + } + ALF{ws}*\n { + mix_byte_t bytes[5]; + memset (bytes, mix_ascii_to_char (' '), 5); + mix_word_t value = mix_bytes_to_word (bytes, 5); + ADD_RAW (value, FALSE); + } + ALF{ws}+({mixchar}{1,5}) { + mix_byte_t bytes[5]; + mix_word_t value; + int i, n; + for (n = 3; n < yyleng; n++) + if (!isspace (yytext[n])) + break; + + for (i = 0; i < 5 && n < yyleng; i++, n++) + bytes[i] = mix_ascii_to_char (yytext[n]); + + for (; i < 5; i++) + bytes[i] = mix_ascii_to_char (' '); + + value = mix_bytes_to_word (bytes, 5); + ADD_RAW (value, FALSE); + } + /* ALF " " */ + [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); +} + + +{ + {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); + } +} + +{ + {number}{ws}*\n | + {number}{ws}+.*\n { + mix_word_t value = mix_word_new (atol (yytext)); + ADD_RAW (value, TRUE); + } +} + +{ + {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); + } +} + +{ + {number}{ws}*\n | + {number}{ws}+.*\n { + parser->start = mix_short_new (atol (yytext)); + parser->end = parser->loc_count; + end = TRUE; + if ( parser->status == MIX_PERR_NOCOMP ) parser->status = MIX_PERR_OK; + return parser->status; + } +} + +{ + {wexpr} ENTER_WEVAL (0); + . RETURN_ERROR (MIX_PERR_INV_OP, yytext); +} + + +{locsymbol} RETURN_ERROR (MIX_PERR_UNEX_LOC, yytext); + +
{ + =/[+-]?{number}= lsf = TRUE; + =/{expr}= lsf = TRUE; + ={wexpr}= { lsf = TRUE; ENTER_WEVAL (1); } + [+-]?{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))); + lsf = FALSE; + ADD_INS (); + } + [+-]?{number}=[(,] { + int pos = yyleng - 3; + if (!lsf) RETURN_ERROR (MIX_PERR_INV_ADDRESS, yytext); + unput (yytext[yyleng - 1]); + while (pos >= 0) { + unput (yytext[pos]); + --pos; + } + } + [+-]?{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); +} + + +{ + {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); +} + +{ + {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); + if (lsf) + { + mix_parser_define_ls (parser, + mix_short_to_word_fast (ins.address)); + ins.address = MIX_WORD_ZERO; + lsf = FALSE; + } + ADD_INS (); + } + } + {expr}/")" { + ENTER_EVAL (); + } + . RETURN_ERROR (MIX_PERR_INV_FSPEC, yytext); +} + + +{ + {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); +} + +{ + {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..b376643 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#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..d3a7461 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..dc56b7a --- /dev/null +++ b/mixlib/mix_symbol_table.c @@ -0,0 +1,198 @@ +/* -*-c-*- -------------- mix_symbol_table.c : + * Implementation of the functions declared in mix_symbol_table.h + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include /* isdigit */ +#include + +#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_t)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, "%-20s: %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..c54c3f8 --- /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, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_SYMBOL_TABLE_H +#define MIX_SYMBOL_TABLE_H + +#include +#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 copying 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..f87247a --- /dev/null +++ b/mixlib/mix_types.c @@ -0,0 +1,569 @@ +/* -*-c-*- ------------------ mix_types.c : + * Implementation file for mix_types.h declarations. + * ------------------------------------------------------------------ + * $Id: mix_types.c,v 1.5 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mix.h" +#include +#include +#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', '~', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', '[', '#', '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_[toupper (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..c628e05 --- /dev/null +++ b/mixlib/mix_types.h @@ -0,0 +1,293 @@ +/* -*-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, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_TYPES_H +#define MIX_TYPES_H + +#include +#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_new(l) (((l) < MIX_CHAR_MAX )? (l) : MIX_CHAR_MAX) +#define mix_char_to_byte(mchar) mix_byte_new (mchar) +#define mix_byte_to_char(byte) mix_char_new (byte) + +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 ) +#define mix_short_reverse_sign(s) ( (s) ^= MIX_SHORT_SIGN_BIT ) + +/* 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..71c8bae --- /dev/null +++ b/mixlib/mix_vm.c @@ -0,0 +1,706 @@ +/* -*-c-*- ------------------ mix_vm.c : + * Implementation of the functions declared in mix_vm.h + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mix.h" +#include "xmix_vm.h" + +#define vm_reset_(vm) vm_reset_reload_ (vm, FALSE); + +static void +vm_reset_reload_ (mix_vm_t *vm, gboolean is_reload) +{ + guint k; + set_status_ (vm, MIX_VM_EMPTY); + 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); + set_last_error_ (vm, MIX_VM_ERROR_NONE); + for ( k = 0; k < MEM_CELLS_NO_; ++k) set_cell_ (vm, k, MIX_WORD_ZERO); + + 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; + } + + for (k = 0; k < BD_NO_; ++k) + if (vm->devices[k] != NULL) + { + mix_device_type_t type = mix_device_type (vm->devices[k]); + if (!is_reload || (type != mix_dev_CONSOLE + && type != mix_dev_PRINTER + && type != mix_dev_CARD_WR)) + { + mix_device_delete (vm->devices[k]); + vm->devices[k] = NULL; + } + } + + if (!is_reload) + mix_vm_clear_all_breakpoints (vm); + + if (vm->address_list) + { + g_slist_free (vm->address_list); + vm->address_list = NULL; + } +} + + +/* 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; + vm->src_file = NULL; + vm->pred_list = mix_predicate_list_new (vm); + vm->address_list = NULL; + vm->last_error = MIX_VM_ERROR_NONE; + + for (i = 0; i < BD_NO_; ++i) + vm->devices[i] = NULL; + + vm->clock = mix_vm_clock_new (); + vm->factory = mix_device_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); + if (vm->pred_list != NULL) mix_predicate_list_delete (vm->pred_list); + if (vm->address_list != NULL) g_slist_free (vm->address_list); + 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; +} + +/* get device */ +mix_device_t * +mix_vm_get_device (const mix_vm_t *vm, mix_device_type_t dev) +{ + g_return_val_if_fail (vm != NULL, NULL); + g_return_val_if_fail (dev < mix_dev_INVALID, NULL); + return vm->devices[dev]; +} + +/* install a device factory for automatic connection */ +void +mix_vm_set_device_factory (mix_vm_t *vm, mix_device_factory_t factory) +{ + g_return_if_fail (vm != NULL); + g_return_if_fail (factory != NULL); + vm->factory = factory; +} + +/* 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); + return (MEMOK_ (addr))? get_cell_ (vm, addr) : MIX_WORD_ZERO; +} + +void +mix_vm_set_addr_contents (mix_vm_t *vm, mix_address_t addr, mix_word_t value) +{ + g_return_if_fail (vm != NULL); + if (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_src_file_t *sfile = NULL; + mix_ins_desc_t ins; + const gchar *sp; + gboolean reload = FALSE; + + g_return_val_if_fail (vm != NULL, FALSE); + file = mix_code_file_new_read (name); + if (file == NULL) + { + set_status_ (vm, MIX_VM_ERROR); + return FALSE; + } + sp = mix_code_file_get_source_path (file); + + if (sp != NULL) + { + sfile = mix_src_file_new_for_read (sp); + reload = (vm->src_file + && !strcmp (mix_src_file_get_path (vm->src_file), + mix_src_file_get_path (sfile))); + } + + vm_reset_reload_ (vm, reload); + + 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_); + } + + vm->src_file = sfile; + + 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); + + set_status_ (vm, MIX_VM_LOADED); + 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); + if (!(MEMOK_ (addr))) return 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_foreach (vm->line_table, get_address_, (gpointer)&tr); + return tr.result; +} + + +/* continue execution of instructions in memory */ +mix_vm_status_t +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); + vm->address_list = + g_slist_prepend (vm->address_list, + GINT_TO_POINTER ((gint)get_loc_ (vm))); + if ( !(*ins_handlers_[ins.opcode]) (vm,&ins) ) + return set_status_ (vm, MIX_VM_ERROR); + else + update_time_ (vm, &ins); + if (bp_is_set_ (vm, get_loc_ (vm))) + return set_status_ (vm, MIX_VM_BREAK); + if (mix_predicate_list_eval (get_pred_list_ (vm))) + return set_status_ (vm, MIX_VM_COND_BREAK); + if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE); + } + return set_status_ (vm, MIX_VM_HALT); +} + +/* execute next memory instruction */ +mix_vm_status_t +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 set_status_ (vm, MIX_VM_HALT); + vm->address_list = + g_slist_prepend (vm->address_list, + GINT_TO_POINTER ((gint)get_loc_ (vm))); + mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); + if (!(*ins_handlers_[ins.opcode]) (vm, &ins)) + return set_status_ (vm, MIX_VM_ERROR); + else + update_time_ (vm, &ins); + if (is_halted_ (vm)) return set_status_ (vm, MIX_VM_HALT); + if (bp_is_set_ (vm, get_loc_ (vm))) return set_status_ (vm, MIX_VM_BREAK); + if (mix_predicate_list_eval (get_pred_list_ (vm))) + return set_status_ (vm, MIX_VM_COND_BREAK); + return set_status_ (vm, MIX_VM_RUNNING); +} + +/* get the current execution status */ +mix_vm_status_t +mix_vm_get_run_status (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); + return get_status_ (vm); +} + +mix_vm_error_t +mix_vm_get_last_error (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, MIX_VM_ERROR_UNEXPECTED); + return get_last_error_ (vm); +} + +const gchar * +mix_vm_get_last_error_string (const mix_vm_t *vm) +{ + return mix_vm_get_error_string (mix_vm_get_last_error (vm)); +} + +const gchar * +mix_vm_get_error_string (mix_vm_error_t code) +{ + static const gchar *errors[] = { + N_("No error"), + N_("Invalid memory address"), + N_("Invalid device number"), + N_("Invalid fspec"), + N_("Invalid M-value"), + N_("Cannot access device"), + N_("Cannot access device for reading"), + N_("Cannot access device for writing"), + N_("Unexpected error"), + N_("Unknow error code") + }; + + return errors[(code < 0 || code > MIX_VM_ERROR_UNEXPECTED) + ? MIX_VM_ERROR_UNEXPECTED + 1 : code]; +} + +/* 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_foreach (vm->line_table, set_break_, (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_foreach (vm->line_table, clear_break_, (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); + mix_predicate_list_clear (get_pred_list_ (vm)); +} + + +gboolean +mix_vm_set_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred) +{ + g_return_val_if_fail (vm != NULL, FALSE); + g_return_val_if_fail (pred != NULL, FALSE); + mix_predicate_list_add (get_pred_list_ (vm), pred); + return TRUE; +} + +gboolean +mix_vm_clear_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred) +{ + g_return_val_if_fail (vm != NULL, FALSE); + g_return_val_if_fail (pred != NULL, FALSE); + return mix_predicate_list_remove (get_pred_list_ (vm), pred); +} + +const gchar * +mix_vm_get_last_breakpoint_message (const mix_vm_t *vm) +{ + const mix_predicate_t *last = NULL; + g_return_val_if_fail (vm != NULL, NULL); + if ((last = mix_predicate_list_last_true_eval (get_pred_list_ (vm))) != NULL) + return mix_predicate_get_message (last); + return NULL; +} + +mix_predicate_type_t +mix_vm_get_last_conditional_breakpoint_type (const mix_vm_t *vm) +{ + const mix_predicate_t *last = NULL; + g_return_val_if_fail (vm != NULL, MIX_PRED_INVALID); + last = mix_predicate_list_last_true_eval (get_pred_list_ (vm)); + return last? mix_predicate_get_type (last) : MIX_PRED_INVALID; +} + +/* 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)); +} + +/* Get the list of addresses for executed instructions */ +const GSList * +mix_vm_get_backtrace (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, NULL); + return get_address_list_ (vm); +} diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h new file mode 100644 index 0000000..12b082a --- /dev/null +++ b/mixlib/mix_vm.h @@ -0,0 +1,255 @@ +/* ---------------------- mix_vm.h : + * Types and functions implementing the MIX virtual machine + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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); + +/* get device */ +extern mix_device_t * +mix_vm_get_device (const mix_vm_t *vm, mix_device_type_t dev); + +/* install a device factory for automatic connection */ +typedef mix_device_t * (* mix_device_factory_t) (mix_device_type_t device); +extern void +mix_vm_set_device_factory (mix_vm_t *vm, mix_device_factory_t factory); + +/* 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); + +/* continue execution of instructions in memory */ +/* Possible outcomes */ +typedef enum { + MIX_VM_ERROR, /* error executing instructions */ + MIX_VM_BREAK, /* breakpoint found */ + MIX_VM_COND_BREAK, /* conditional breakpoint found */ + MIX_VM_HALT, /* end of execution */ + MIX_VM_RUNNING, /* successful instruction execution */ + MIX_VM_LOADED, /* program loaded */ + MIX_VM_EMPTY /* no program loaded */ +} mix_vm_status_t; + +/* execution errors */ +typedef enum { + MIX_VM_ERROR_NONE, /* no error */ + MIX_VM_ERROR_BAD_ACCESS, /* bad memory address */ + MIX_VM_ERROR_BAD_DEVICE_NO, /* bad device number */ + MIX_VM_ERROR_BAD_FSPEC, /* invalid fspec */ + MIX_VM_ERROR_BAD_M, /* invalid M-value */ + MIX_VM_ERROR_DEV_CTL, /* error accessing device for ioctl */ + MIX_VM_ERROR_DEV_READ, /* error accessing device for reading */ + MIX_VM_ERROR_DEV_WRITE, /* error accessing device for writing */ + MIX_VM_ERROR_UNEXPECTED /* unexpected error */ +} mix_vm_error_t; + +extern mix_vm_error_t +mix_vm_get_last_error (const mix_vm_t *vm); + +extern const gchar * +mix_vm_get_last_error_string (const mix_vm_t *vm); + +extern const gchar * +mix_vm_get_error_string (mix_vm_error_t code); + +/* run until next breakpoint or end of execution */ +extern mix_vm_status_t +mix_vm_run (mix_vm_t *vm); + +/* execute next memory instruction */ +extern mix_vm_status_t +mix_vm_exec_next (mix_vm_t *vm); + +/* get the current execution status */ +extern mix_vm_status_t +mix_vm_get_run_status (const 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); + +#include "mix_predicate.h" +extern gboolean +mix_vm_set_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred); + +extern gboolean +mix_vm_clear_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred); + +extern const gchar * +mix_vm_get_last_breakpoint_message (const mix_vm_t *vm); + +extern mix_predicate_type_t +mix_vm_get_last_conditional_breakpoint_type (const 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); + +/* Get the list of addresses for executed instructions */ +extern const GSList * +mix_vm_get_backtrace (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..cc39992 --- /dev/null +++ b/mixlib/mix_vm_clock.c @@ -0,0 +1,70 @@ +/* -*-c-*- -------------- mix_vm_clock.c : + * Implementation of the functions declared in mix_vm_clock.h + * ------------------------------------------------------------------ + * $Id: mix_vm_clock.c,v 1.3 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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_opMOVE) { + 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..3c19973 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..350dae5 --- /dev/null +++ b/mixlib/mix_vm_command.c @@ -0,0 +1,641 @@ +/* -*-c-*- -------------- mix_vm_command.c : + * Implementation of the functions declared in mix_vm_command.h + * ------------------------------------------------------------------ + * $Id: mix_vm_command.c,v 1.30 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "xmix_vm_command.h" +#include "xmix_vm_handlers.h" + +#ifdef HAVE_LIBHISTORY +# include +#endif + +#ifdef HAVE_LIBREADLINE +# include +#endif + +/* hook execution */ +static void +exec_hook_list_ (GSList *list, mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + while (list) + { + hook_ *hook = (hook_ *)list->data; + if (hook) + (hook->func)(dis, arg, hook->data); + list = list->next; + } +} + +static void +exec_global_hook_list_ (GSList *list, + mix_vm_cmd_dispatcher_t *dis, + mix_vm_command_t cmd, const gchar *arg) +{ + while (list) + { + global_hook_ *hook = (global_hook_ *)list->data; + if (hook) + (hook->func)(dis, cmd, arg, hook->data); + list = list->next; + } +} + +/* 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) +{ + 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 */ +static GCompletion * +make_completions_ (void) +{ + GList *cmds = NULL; + gint k; + + GCompletion *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 (completions, cmds); + return completions; +} + +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->log_msg = TRUE; + result->uptime = result->laptime = result->progtime = 0; + result->printtime = TRUE; + result->trace = FALSE; + result->program = NULL; + result->editor = NULL; + result->assembler = 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 = result->global_post = NULL; + + for (k =0; k < MIX_CMD_INVALID; ++k) + result->pre_hooks[k] = result->post_hooks[k] = NULL; + + result->config = NULL; + + for (k = 0; k < PRNO_; ++k) + result->preds[k] = mix_predicate_new (k); + + result->mem_preds = g_hash_table_new (NULL, NULL); + result->commands = g_hash_table_new (g_str_hash, g_str_equal); + result->completions = make_completions_ (); + + return result; +} + +mix_vm_cmd_dispatcher_t * +mix_vm_cmd_dispatcher_new_with_config (FILE *out, FILE *err, + mix_config_t *config) +{ + mix_vm_cmd_dispatcher_t *result = mix_vm_cmd_dispatcher_new (out, err); + if (result != NULL && (result->config = config) != NULL) + { + gint hsize = 0; + const gchar *val = mix_config_get (result->config, TRACING_KEY_); + if (val) cmd_strace_ (result, val); + val = mix_config_get (result->config, EDITOR_KEY_); + if (val) mix_vm_cmd_dispatcher_set_editor (result, val); + val = mix_config_get (result->config, ASM_KEY_); + if (val) mix_vm_cmd_dispatcher_set_assembler (result, val); + val = mix_config_get (result->config, TIMING_KEY_); + if (val) cmd_stime_ (result, val); + val = mix_config_get_devices_dir (result->config); + if (!val || !mix_stat_dir (val, "devices")) + { + gchar *dirname = + g_path_get_dirname (mix_config_get_filename (config)); + cmd_sddir_ (result, dirname); + g_free (dirname); + } + else + mix_device_set_dir (val); + val = mix_config_get (result->config, LOGGING_KEY_); + if (val) cmd_slog_ (result, val); +#ifdef HAVE_LIBHISTORY + val = mix_config_get_history_file (result->config); + hsize = mix_config_get_history_size (result->config); + using_history (); + stifle_history (hsize); + if (val) + { + read_history ((char *)val); + history_set_pos (history_base + history_length - 1); + } +#endif + } + return result; +} + + +/* delete (does not close the fds in the constructor) */ +static gboolean +del_pred_ (gpointer key, gpointer val, gpointer data) +{ + if (val) mix_predicate_delete ((mix_predicate_t *)val); + return TRUE; +} + +static void +del_hook_ (gpointer data, gpointer ignored) +{ + if (data) g_free (data); +} + +static void +del_hook_list_ (GSList *s) +{ + if (s) + { + g_slist_foreach (s, del_hook_, NULL); + g_slist_free (s); + } +} + +void +mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis) +{ + const gchar *hfile = NULL; + gint k; + + g_return_if_fail (dis != NULL); + mix_eval_delete (dis->eval); + mix_dump_context_delete (dis->dump); + mix_vm_delete (dis->vm); + if (dis->editor) g_free (dis->editor); + if (dis->editor) g_free (dis->assembler); +#ifdef HAVE_LIBHISTORY + if (dis->config && (hfile = mix_config_get_history_file + (dis->config))) + write_history ((char *)hfile); +#endif + for (k = 0; k < PRNO_; ++k) mix_predicate_delete (dis->preds[k]); + g_hash_table_foreach_remove (dis->mem_preds, del_pred_, NULL); + g_hash_table_destroy (dis->mem_preds); + g_hash_table_destroy (dis->commands); + g_completion_free (dis->completions); + for (k = 0; k < MIX_CMD_INVALID; ++k) + { + del_hook_list_ (dis->pre_hooks[k]); + del_hook_list_ (dis->post_hooks[k]); + } + del_hook_list_ (dis->global_pre); + del_hook_list_ (dis->global_post); + g_free (dis); +} + +/* register new commands for a dispatcher */ +void +mix_vm_cmd_dispatcher_register_new (mix_vm_cmd_dispatcher_t *dis, + mix_vm_command_info_t *cmd) +{ + GList *list = NULL; + g_return_if_fail (dis != NULL); + g_return_if_fail (cmd != NULL); + g_hash_table_insert (dis->commands, (gpointer)cmd->name, (gpointer)cmd); + list = g_list_append (list, (gpointer)cmd->name); + g_completion_add_items (dis->completions, list); +} + +const GList * +mix_vm_cmd_dispatcher_complete (const mix_vm_cmd_dispatcher_t *dis, + const gchar *cmd, gchar **prefix) +{ + char *cp; + GList *result; + + g_return_val_if_fail (dis != NULL, NULL); + g_return_val_if_fail (cmd != NULL, NULL); + + cp = g_strdup (cmd); + result = g_completion_complete (dis->completions, cp, prefix); + g_free (cp); + return result; +} + +/* set/get out/error streams */ +FILE * +mix_vm_cmd_dispatcher_get_out_stream (const mix_vm_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis, NULL); + return dis->out; +} + +FILE * +mix_vm_cmd_dispatcher_get_err_stream (const mix_vm_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis, NULL); + return dis->err; +} + +FILE * /* old output stream */ +mix_vm_cmd_dispatcher_set_out_stream (mix_vm_cmd_dispatcher_t *dis, FILE *out) +{ + FILE *old = NULL; + g_return_val_if_fail (dis != NULL, old); + old = dis->out; + dis->out = out; + dis->dump->channel = out; + return old; +} + +FILE * /* old error stream */ +mix_vm_cmd_dispatcher_set_error_stream (mix_vm_cmd_dispatcher_t *dis, + FILE *err) +{ + FILE *old = NULL; + g_return_val_if_fail (dis != NULL, old); + old = dis->err; + dis->err = err; + return old; +} + + +/* set editor and compiler templates */ +void +mix_vm_cmd_dispatcher_set_editor (mix_vm_cmd_dispatcher_t *dis, + const gchar *edit_tplt) +{ + g_return_if_fail (dis != NULL); + if (dis->editor) g_free (dis->editor); + dis->editor = (edit_tplt) ? g_strdup (edit_tplt) : NULL; + if (dis->config && dis->editor) + mix_config_update (dis->config, EDITOR_KEY_, dis->editor); +} + +void +mix_vm_cmd_dispatcher_set_assembler (mix_vm_cmd_dispatcher_t *dis, + const gchar *asm_tplt) +{ + g_return_if_fail (dis != NULL); + if (dis->assembler) g_free (dis->assembler); + dis->assembler = (asm_tplt) ? g_strdup (asm_tplt) : NULL; + if (dis->config && dis->assembler) + mix_config_update (dis->config, ASM_KEY_, dis->assembler); +} + +const gchar * +mix_vm_cmd_dispatcher_get_editor (const mix_vm_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis != NULL, NULL); + return dis->editor; +} + +const gchar * +mix_vm_cmd_dispatcher_get_assembler (const mix_vm_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis != NULL, NULL); + return dis->assembler; +} + +const gchar * +mix_vm_cmd_dispatcher_get_src_file_path (const mix_vm_cmd_dispatcher_t *dis) +{ + static gchar *PATH = NULL; + + const mix_vm_t *vm = mix_vm_cmd_dispatcher_get_vm (dis); + const mix_src_file_t *f = mix_vm_get_src_file (vm); + + if (PATH) + { + g_free (PATH); + PATH = NULL; + } + + if (f) + PATH = mix_file_complete_name (mix_src_file_get_path (f), MIX_SRC_DEFEXT); + + return PATH; +} + +const gchar * +mix_vm_cmd_dispatcher_get_program_path (const mix_vm_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis != NULL, NULL); + return dis->program; +} + +/* 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) +{ + hook_ *phook; + + g_return_if_fail (dis != NULL); + g_return_if_fail (cmd < MIX_CMD_INVALID); + + phook = g_new (hook_, 1); + phook->func = hook; + phook->data = data; + + dis->pre_hooks[cmd] = g_slist_append (dis->pre_hooks[cmd], phook); +} + +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) +{ + hook_ *phook; + + g_return_if_fail (dis != NULL); + g_return_if_fail (cmd < MIX_CMD_INVALID); + + phook = g_new (hook_, 1); + phook->func = hook; + phook->data = data; + + dis->post_hooks[cmd] = g_slist_append (dis->post_hooks[cmd], phook); +} + +void +mix_vm_cmd_dispatcher_global_pre_hook (mix_vm_cmd_dispatcher_t *dis, + mix_vm_cmd_global_hook_t hook, + gpointer data) +{ + global_hook_ *phook; + + g_return_if_fail (dis != NULL); + + phook = g_new (global_hook_, 1); + phook->func = hook; + phook->data = data; + + dis->global_pre = g_slist_append (dis->global_pre, phook); +} + +void +mix_vm_cmd_dispatcher_global_post_hook (mix_vm_cmd_dispatcher_t *dis, + mix_vm_cmd_global_hook_t hook, + gpointer data) +{ + global_hook_ *phook; + + g_return_if_fail (dis != NULL); + + phook = g_new (global_hook_, 1); + phook->func = hook; + phook->data = data; + + dis->global_post = g_slist_append (dis->global_post, phook); +} + +/* 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) + exec_global_hook_list_ (dis->global_pre, dis, cmd, arg); + + if (cmd < MIX_CMD_INVALID) + { + if (dis->pre_hooks[cmd]) + exec_hook_list_ (dis->pre_hooks[cmd], dis, arg); + + fflush (dis->out); + fflush (dis->err); + + dis->result = (commands_[cmd].func)(dis, arg); + + fflush (dis->out); + fflush (dis->err); + + if (dis->post_hooks[cmd]) + exec_hook_list_ (dis->post_hooks[cmd], dis, arg); + + fflush (dis->out); + fflush (dis->err); + } + else + { + fprintf (dis->err, _("Unknown command. Try: help\n")); + } + + if (dis->global_post) + exec_global_hook_list_ (dis->global_post, dis, cmd, arg); + + 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; + + 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; + } + + (void) mix_vm_cmd_dispatcher_dispatch_split_text (dis, cp, arg); + + g_free (cp); + + return dis->result; +} + +/* dispatch a command in text format, with command and arg split */ +gboolean +mix_vm_cmd_dispatcher_dispatch_split_text (mix_vm_cmd_dispatcher_t *dis, + const gchar *command, + const gchar *arg) +{ + mix_vm_command_info_t *info; + + g_return_val_if_fail (dis, FALSE); + + if (!command) return FALSE; + if (!arg) arg = ""; + + info = (mix_vm_command_info_t *)g_hash_table_lookup (dis->commands, command); + + if (info) + { + if (dis->global_pre) + exec_global_hook_list_ (dis->global_pre, dis, MIX_CMD_LOCAL, arg); + + fflush (dis->out); + fflush (dis->err); + + dis->result = info->func (dis, arg); + + fflush (dis->out); + fflush (dis->err); + + if (dis->global_post) + exec_global_hook_list_ (dis->global_post, dis, MIX_CMD_LOCAL, arg); + + fflush (dis->out); + fflush (dis->err); + } + else + dis->result = + mix_vm_cmd_dispatcher_dispatch (dis, + mix_vm_command_from_string (command), + arg); + return dis->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; +} + +/* src file info */ +gulong +mix_vm_cmd_dispatcher_get_src_file_lineno (const mix_vm_cmd_dispatcher_t *dis) +{ + g_return_val_if_fail (dis != NULL, 0); + return mix_vm_get_break_lineno (dis->vm); +} + +const gchar * +mix_vm_cmd_dispatcher_get_src_file_line (const mix_vm_cmd_dispatcher_t *dis, + gulong line, gboolean cr) +{ + const mix_src_file_t *file; + g_return_val_if_fail (dis != NULL, NULL); + + file = mix_vm_get_src_file (dis->vm); + + if (line == 0 || file == NULL) return cr? "" : "\n"; + + if (cr) + return mix_src_file_get_line (file, line); + else + { + enum {BUFF_SIZE = 256}; + static gchar BUFFER[BUFF_SIZE]; + int len = + g_snprintf (BUFFER, BUFF_SIZE, "%s", mix_src_file_get_line (file, line)); + if (len > 0 && BUFFER[len - 1] == '\n') BUFFER[len - 1] = '\0'; + return BUFFER; + } +} + + diff --git a/mixlib/mix_vm_command.h b/mixlib/mix_vm_command.h new file mode 100644 index 0000000..1ff561f --- /dev/null +++ b/mixlib/mix_vm_command.h @@ -0,0 +1,256 @@ +/* -*-c-*- ---------------- mix_vm_command.h : + * declarations for mix_vm_command_t, describing commands issued to a vm + * ------------------------------------------------------------------ + * $Id: mix_vm_command.h,v 1.15 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIX_VM_COMMAND_H +#define MIX_VM_COMMAND_H + +#include +#include "mix.h" +#include "mix_vm.h" +#include "mix_config.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_EDIT, /* edit mixal source */ + MIX_CMD_PEDIT, /* print editor command */ + MIX_CMD_SEDIT, /* set editor command*/ + MIX_CMD_COMPILE, /* compile mixal source */ + MIX_CMD_PASM, /* print compiler command */ + MIX_CMD_SASM, /* set assembler command */ + MIX_CMD_RUN, /* run a loaded program */ + MIX_CMD_NEXT, /* run next instruction */ + MIX_CMD_PSTAT, /* print current vm status */ + 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_SBPR, /* set breakpoint on register changed */ + MIX_CMD_CBPR, /* clear breakpoint on register changed */ + MIX_CMD_SBPM, /* set breakpoint on mem cell changed */ + MIX_CMD_CBPM, /* clear breakpoint on mem cell changed */ + MIX_CMD_SBPC, /* set breakpoint on comp flag changed */ + MIX_CMD_CBPC, /* clear breakpoint on comp flag changed */ + MIX_CMD_SBPO, /* set breakpoint on overflow toggled */ + MIX_CMD_CBPO, /* clear breakpoint on overflow toggled */ + MIX_CMD_CABP, /* clear all breakpoints */ + MIX_CMD_WEVAL, /* evaluate a w-expression */ + MIX_CMD_W2D, /* print word in decimal notation */ + MIX_CMD_STRACE, /* enable/disable instruction traces */ + MIX_CMD_PBT, /* print backtrace */ + MIX_CMD_STIME, /* enable/disable timing statistics */ + MIX_CMD_PTIME, /* print current time statistics */ + MIX_CMD_SDDIR, /* set device directory */ + MIX_CMD_PDDIR, /* print current device directory */ + MIX_CMD_SLOG, /* set on/off message logging */ + MIX_CMD_PPROG, /* print the current program path */ + MIX_CMD_PSRC, /* print the current program source path */ + MIx_CMD_PLINE, /* print the current line no */ + MIX_CMD_INVALID, /* invalid command identifier */ + MIX_CMD_LOCAL /* locally defined command */ +} mix_vm_command_t; + +/* new commands definition */ +typedef gboolean (*mix_vm_cmd_function_t) (mix_vm_cmd_dispatcher_t *, + const gchar *); +typedef struct { + const gchar *name; /* User printable name of the function. */ + mix_vm_cmd_function_t func; /* Function to call to do the job. */ + const char *doc; /* Documentation for this function. */ + const char *usage; /* Usage */ +} mix_vm_command_info_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, /* output messages file */ + FILE *err /* error messages file */); + +extern mix_vm_cmd_dispatcher_t * +mix_vm_cmd_dispatcher_new_with_config (FILE *out, FILE *err, + mix_config_t *config); + +/* delete (does not close the fds in the constructor) */ +extern void +mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis); + +/* register new commands for a dispatcher */ +extern void +mix_vm_cmd_dispatcher_register_new (mix_vm_cmd_dispatcher_t *dis, + mix_vm_command_info_t *cmd); + +/* get command completion list */ +const GList * +mix_vm_cmd_dispatcher_complete (const mix_vm_cmd_dispatcher_t *dis, + const gchar *cmd, gchar **prefix); + +/* set/get out/error streams */ +extern FILE * +mix_vm_cmd_dispatcher_get_out_stream (const mix_vm_cmd_dispatcher_t *dis); + +extern FILE * +mix_vm_cmd_dispatcher_get_err_stream (const mix_vm_cmd_dispatcher_t *dis); + +extern FILE * /* old output stream */ +mix_vm_cmd_dispatcher_set_out_stream (mix_vm_cmd_dispatcher_t *dis, + FILE *out); + +extern FILE * /* old error stream */ +mix_vm_cmd_dispatcher_set_error_stream (mix_vm_cmd_dispatcher_t *dis, + FILE *err); + +/* set editor and compiler templates */ +extern void +mix_vm_cmd_dispatcher_set_editor (mix_vm_cmd_dispatcher_t *dis, + const gchar *edit_tplt); + +extern void +mix_vm_cmd_dispatcher_set_assembler (mix_vm_cmd_dispatcher_t *dis, + const gchar *asm_tplt); + +extern const gchar * +mix_vm_cmd_dispatcher_get_src_file_path (const mix_vm_cmd_dispatcher_t *dis); + +extern const gchar * +mix_vm_cmd_dispatcher_get_program_path (const mix_vm_cmd_dispatcher_t *dis); + +extern const gchar * +mix_vm_cmd_dispatcher_get_editor (const mix_vm_cmd_dispatcher_t *dis); + +extern const gchar * +mix_vm_cmd_dispatcher_get_assembler (const 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); + +/* dispatch a command in text format, with command and arg split */ +extern gboolean +mix_vm_cmd_dispatcher_dispatch_split_text (mix_vm_cmd_dispatcher_t *dis, + const gchar *command, + const gchar *arg); + +/* 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); + +/* src file info */ +extern gulong +mix_vm_cmd_dispatcher_get_src_file_lineno (const mix_vm_cmd_dispatcher_t *dis); + +extern const gchar * +mix_vm_cmd_dispatcher_get_src_file_line (const mix_vm_cmd_dispatcher_t *dis, + gulong line, gboolean cr); + +/* 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..5c0bc32 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include "mix.h" +#include +#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<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..7f8b0c3 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#ifndef MIX_VM_DUMP_H +#define MIX_VM_DUMP_H + +#include +#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/Makefile.am b/mixlib/testsuite/Makefile.am new file mode 100644 index 0000000..834f833 --- /dev/null +++ b/mixlib/testsuite/Makefile.am @@ -0,0 +1,32 @@ +## 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. + +# $Id: Makefile.am,v 1.2 2001/09/29 01:53:51 jao Exp $ + +INCLUDES = -I$(includedir) -I$(top_srcdir) -I$(top_srcdir)/mixlib +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..8638d2f --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include + +/* 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..9b62fd6 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include +/* 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..8dcc619 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include +#include + +/* 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..215fc70 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include + +/* 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..ababead --- /dev/null +++ b/mixlib/testsuite/mix_types_t.c @@ -0,0 +1,369 @@ +/*----------------------- mix_types_t.c ----------------------------- + * Tests for mix_types.h + * ------------------------------------------------------------------ +* +** Copyright (C) 1999, 2004 Free Software Foundation, Inc. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#include +#include + +/* 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("\nchar <-> byte conversions...\n"); + + for (k = 0; k < MIX_CHAR_MAX + 1; ++k) { + mix_byte_t c = mix_byte_new (k); + g_assert (c == mix_byte_to_char (mix_char_to_byte (c))); + } + + 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..458cbba --- /dev/null +++ b/mixlib/testsuite/mix_vm_ins_t.c @@ -0,0 +1,505 @@ +/* ---------------------- mix_vm_ins_t.c : + * Tests for the virtual machine instruction handlers. + * ------------------------------------------------------------------ +** Copyright (C) 2000, 2004 Free Software Foundation, Inc. +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + + +#include +/* #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_new_b(0,0,0,0,1), + MIX_WORD_MINUS_ZERO, + mix_word_new_b(1,16,3,5,4), + mix_word_new_bn(1,16,3,5,4), + mix_word_new_bn(0,0,3,5,4), + mix_word_new_b(0,0,1,16,3), + mix_word_new_bn(0,0,0,0,5), + mix_word_new_bn(0,0,0,0,1), + MIX_WORD_ZERO + }; + mix_fspec_t fs[11] = {5,13,29,3,36,9,0,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_negative (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..7f8eb0c --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +/* Common definitions for test programs */ + +#ifndef TEST_H +#define TEST_H + +#include +#include + +#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..c61ab55 --- /dev/null +++ b/mixlib/xmix_device.c @@ -0,0 +1,199 @@ +/* -*-c-*- -------------- xmix_device.c : + * Implementation of the functions declared in xmix_device.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "2001-05-10 01:10:25 jao" + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "xmix_device.h" +#include "mix_types.h" + +gchar *DEV_DIR_ = NULL; + +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_RDWRT, mix_io_READ +}; + +/* constructors */ +void +construct_device_ (mix_device_t *result, mix_device_type_t type) +{ + gchar *name; + name = DEV_DIR_ ? g_strdup_printf ("%s/%s", DEV_DIR_, DEF_NAMES_[type]) + : g_strdup (DEF_NAMES_[type]); + construct_device_with_name_ (result, type, name); + g_free (name); +} + + +void +construct_device_with_name_ (mix_device_t *result, + mix_device_type_t type, const gchar *name) +{ + result->type = type; + if (type != mix_dev_CONSOLE) + { + result->file = MIX_IOCHANNEL(mix_file_new_with_def_ext (name, + FMODES_[type], + DEV_EXT_)); + result->vtable = DEF_DEV_VTABLE_; + } + else + { + result->file = mix_io_new (stdout); + result->vtable = CONSOLE_DEV_VTABLE_; + } +} + + +void +construct_device_with_file_ (mix_device_t *result, + mix_device_type_t type, FILE *file) +{ + result->type = type; + result->file = mix_io_new (file); + result->vtable = DEF_DEV_VTABLE_; +} + + +/* + 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]); + fflush (mix_io_to_FILE (GET_CHANNEL_ (dev))); + + return result; +} + +static gboolean +read_cons_ (mix_device_t *dev, mix_word_t *block) +{ + return mix_io_read_word_array_as_char (mix_io_new (stdin), block, + SIZES_[mix_dev_CONSOLE]); +} + +static gboolean +read_ (mix_device_t *dev, mix_word_t *block) +{ + gboolean result; + + if (FMODES_[dev->type] == mix_io_WRITE) return FALSE; + if (MODES_[dev->type] == mix_dev_CHAR) + { + result = mix_io_read_word_array_as_char (GET_CHANNEL_ (dev), + block, SIZES_[dev->type]); + } + else + result = mix_io_read_word_array (GET_CHANNEL_ (dev), + block, SIZES_[dev->type]); + + return result; +} + +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) + { + if (m == 0) return FALSE; + // position disk + } + if (dev->type == mix_dev_PAPER_TAPE) + { + if (m == 0) return FALSE; + rewind (file); + } + return TRUE; +} + +static gboolean +busy_ (const mix_device_t *dev) +{ + return (!mix_io_is_ready (GET_CHANNEL_(dev))); +} + +static void +destroy_ (mix_device_t *dev) +{ + if (dev->type != mix_dev_CONSOLE && GET_FILE_(dev) != NULL) + mix_file_delete (GET_FILE_(dev)); +} + +static mix_device_vtable_t VTABLE_ = { + write_, read_, ioc_, busy_, destroy_ +}; + +const mix_device_vtable_t * DEF_DEV_VTABLE_ = &VTABLE_; + +static mix_device_vtable_t CVTABLE_ = { + write_, read_cons_, ioc_, busy_, destroy_ +}; + +const mix_device_vtable_t * CONSOLE_DEV_VTABLE_ = &CVTABLE_; diff --git a/mixlib/xmix_device.h b/mixlib/xmix_device.h new file mode 100644 index 0000000..0eb3fa8 --- /dev/null +++ b/mixlib/xmix_device.h @@ -0,0 +1,96 @@ +/* -*-c-*- ---------------- xmix_device.h : + * Protected declarations for mix_device_t + * ------------------------------------------------------------------ + * Last change: Time-stamp: <2001-05-07 23:59:35 jao> + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef XMIX_DEVICE_H +#define XMIX_DEVICE_H + +#include "mix_file.h" +#include "mix_device.h" + +/* device file directory */ +extern gchar *DEV_DIR_; + +/* 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 void (*mix_dev_destroy_t) (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_dev_destroy_t destroy; +} mix_device_vtable_t; + +/* default vtables */ +extern const mix_device_vtable_t *DEF_DEV_VTABLE_; +extern const mix_device_vtable_t *CONSOLE_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; +}; + +/* constructors */ +extern void +construct_device_ (mix_device_t *dev, mix_device_type_t type); + +extern void +construct_device_with_name_ (mix_device_t *dev, + mix_device_type_t type, const gchar *name); + +extern void +construct_device_with_file_ (mix_device_t *dev, + mix_device_type_t type, FILE *file); + + +#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..7516ed3 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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..a43d284 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#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); + if (mode == mix_io_RDWRT) rewind (file); + 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..1346559 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef XMIX_IOCHANNEL_H +#define XMIX_IOCHANNEL_H + +#include +#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..51f1560 --- /dev/null +++ b/mixlib/xmix_parser.h @@ -0,0 +1,111 @@ +/* -*-c-*- ---------------- xmix_parser.h : + * Declarations for the implementation of mix_parser_t + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 */ + GSList *con_list; /* CON instructions */ + GSList *alf_list; /* ALF 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 */ + mix_address_t end; /* end 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, + gboolean is_con); + +/* 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..d5b4e4b --- /dev/null +++ b/mixlib/xmix_vm.c @@ -0,0 +1,598 @@ +/* ---------------------- xmix_vm.c : + * Implementation of the functions declared in xmix_vm.h + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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] = vm->factory (type); + return vm->devices[type]; +} + +/* error macro */ +#define fail_if_not_(vm,cond,error) \ +do { \ + if (!(cond)) \ + { \ + set_last_error_ (vm, error); \ + return FALSE; \ + } \ +} while (FALSE) + +#define fail_(vm,error) fail_if_not_ (vm, FALSE, error) + +#define fail_unexpected_(vm) fail_ (vm, MIX_VM_ERROR_UNEXPECTED) + +/* 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: fail_ (vm, MIX_VM_ERROR_BAD_FSPEC); + } + 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); + + fail_if_not_ (vm, mix_short_is_positive (n), MIX_VM_ERROR_BAD_M); + + 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: + fail_unexpected_ (vm); + } + + 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); + if (mix_short_is_positive (from) + && mix_short_is_positive (to) + && MEMOK_ (from + delta -1) + && MEMOK_ (to + delta - 1)) + { + 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; + } + else + return FALSE; +} + +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_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); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + fail_if_not_ (vm, get_dev_ (vm, ins->fspec) != NULL, + MIX_VM_ERROR_BAD_DEVICE_NO); + + 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; + + g_assert (ins->opcode == mix_opIOC); + + addr = get_M_ (vm, ins); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + + dev = get_dev_ (vm, ins->fspec); + fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); + + fail_if_not_ (vm, mix_device_ioc (dev, addr), MIX_VM_ERROR_DEV_CTL); + + inc_loc_ (vm); + return TRUE; +} + +static gboolean +inp_handler_ (mix_vm_t *vm, const mix_ins_t *ins) +{ + mix_address_t addr; + mix_device_t *dev; + + g_assert (ins->opcode == mix_opIN); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + + addr = get_M_ (vm, ins); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + + dev = get_dev_ (vm, ins->fspec); + fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); + + fail_if_not_ (vm, MEM_CELLS_NO_ - addr > mix_device_block_size (dev), + MIX_VM_ERROR_BAD_ACCESS); + + fail_if_not_ (vm, mix_device_read (dev, get_cell_ptr_ (vm, addr)), + MIX_VM_ERROR_DEV_READ); + + inc_loc_ (vm); + return TRUE; +} + +static gboolean +out_handler_ (mix_vm_t *vm, const mix_ins_t *ins) +{ + mix_address_t addr; + mix_device_t *dev; + + g_assert (ins->opcode == mix_opOUT); + + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + + addr = get_M_ (vm, ins); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + + dev = get_dev_ (vm, ins->fspec); + fail_if_not_ (vm, dev != NULL, MIX_VM_ERROR_BAD_DEVICE_NO); + + fail_if_not_ (vm, MEM_CELLS_NO_ - addr > mix_device_block_size (dev), + MIX_VM_ERROR_BAD_ACCESS); + + fail_if_not_ (vm, mix_device_write (dev, get_cell_ptr_ (vm, addr)), + MIX_VM_ERROR_DEV_WRITE); + + inc_loc_ (vm); + return TRUE; +} + +static gboolean +jrd_handler_ (mix_vm_t *vm, const mix_ins_t *ins) +{ + g_assert (ins->opcode == mix_opJRED); + fail_if_not_ (vm, ins->fspec < BD_NO_, MIX_VM_ERROR_BAD_DEVICE_NO); + fail_if_not_ (vm, get_dev_ (vm, ins->fspec) != NULL, + MIX_VM_ERROR_BAD_DEVICE_NO); + + 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); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + + 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: + fail_unexpected_ (vm); + } + + 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); + fail_if_not_ (vm, MEMOK_ (addr), MIX_VM_ERROR_BAD_ACCESS); + + 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: + fail_unexpected_ (vm); + } + + 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: + fail_unexpected_ (vm); + } + 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, ®); + 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..7a634d4 --- /dev/null +++ b/mixlib/xmix_vm.h @@ -0,0 +1,139 @@ +/* ---------------------- xmix_vm.h : + * This file contains internal declarations used in the implementation + * of the mix_vm_t type. + * ------------------------------------------------------------------ + * $Id: xmix_vm.h,v 1.10 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef XMIX_VM_H +#define XMIX_VM_H + +#include + +#include "mix_symbol_table.h" +#include "mix_device.h" +#include "mix_src_file.h" +#include "mix_predicate_list.h" +#include "mix_vm.h" + +/* The mix_vm_t type */ +enum { + IREG_NO_ = 6, + BD_NO_ = 21, + MEM_CELLS_NO_ = MIX_VM_CELL_NO, + MEM_CELLS_MAX_ = MIX_VM_CELL_NO - 1 +}; + +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; + mix_vm_status_t status; + mix_vm_error_t last_error; + 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 */ + mix_device_factory_t factory; /* the factory for new devices */ + mix_predicate_list_t *pred_list; /* predicates for conditional bps */ + GSList *address_list; /* list of executed addresses */ +}; + +/* 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 get_pred_list_(vm) (vm->pred_list) +#define get_address_list_(vm) (vm->address_list) +#define get_status_(vm) (vm->status) +#define get_last_error_(vm) (vm->last_error) +#define set_last_error_(vm,error) ((vm)->last_error = (error)) + +#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 = (MEMOK_(x)? (x) : MIX_SHORT_ZERO) + +#define set_status_(vm,s) ((vm)->status = (s)) +#define is_halted_(vm) ((vm)->status == MIX_VM_HALT) +#define halt_(vm,val) ((vm)->status = (val)? MIX_VM_HALT : MIX_VM_RUNNING) + +#define inc_loc_(vm) \ +do { \ + if (++(vm->loc_count) == MEM_CELLS_NO_) \ + { vm->loc_count--; halt_(vm, TRUE); } \ +} while(FALSE) + +#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/mixlib/xmix_vm_command.c b/mixlib/xmix_vm_command.c new file mode 100644 index 0000000..370ffb7 --- /dev/null +++ b/mixlib/xmix_vm_command.c @@ -0,0 +1,64 @@ +/* -*-c-*- -------------- xmix_vm_command.c : + * Implementation of the functions declared in xmix_vm_command.h + * ------------------------------------------------------------------ + * $Id: xmix_vm_command.c,v 1.4 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include + +#include "xmix_vm_command.h" + +/* configuration keys */ +const gchar *TRACING_KEY_ = "Tracing"; +const gchar *TIMING_KEY_ = "Timing"; +const gchar *EDITOR_KEY_ = "Editor"; +const gchar *ASM_KEY_ = "Assembler"; +const gchar *LOGGING_KEY_ = "Logs"; + +void +log_message_ (mix_vm_cmd_dispatcher_t *dis, const gchar *fmt, ...) +{ + if (dis && fmt && dis->log_msg && dis->out) + { + va_list args; + va_start (args, fmt); + vfprintf (dis->out, fmt, args); + fprintf (dis->out, "\n"); + va_end (args); + } +} + + +extern void +log_error_ (mix_vm_cmd_dispatcher_t *dis, const gchar *fmt, ...) +{ + enum {BUFF_SIZE = 256}; + static gchar BUFFER[256]; + + if (dis && fmt && dis->err) + { + va_list args; + va_start (args, fmt); + g_snprintf (BUFFER, BUFF_SIZE, "ERROR: %s\n", fmt); + vfprintf (dis->err, BUFFER, args); + va_end (args); + } +} diff --git a/mixlib/xmix_vm_command.h b/mixlib/xmix_vm_command.h new file mode 100644 index 0000000..ae2c2e7 --- /dev/null +++ b/mixlib/xmix_vm_command.h @@ -0,0 +1,102 @@ +/* -*-c-*- ---------------- xmix_vm_command.h : + * Private type declarations form mix_vm_command + * ------------------------------------------------------------------ + * $Id: xmix_vm_command.h,v 1.5 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef XMIX_VM_COMMAND_H +#define XMIX_VM_COMMAND_H + +#include +#include +#include +#include +#include + +#include "mix.h" +#include "mix_device.h" +#include "mix_vm.h" +#include "mix_vm_dump.h" +#include "mix_eval.h" +#include "mix_predicate.h" +#include "mix_vm_command.h" + + +/* configuration keys */ +extern const gchar *TRACING_KEY_; +extern const gchar *TIMING_KEY_; +extern const gchar *EDITOR_KEY_; +extern const gchar *ASM_KEY_; +extern const gchar *LOGGING_KEY_; + +/* 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_; + +enum {PRNO_ = MIX_PRED_MEM, HOOKNO_ = MIX_CMD_INVALID}; + +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 */ + gchar *editor; /* edit command line template */ + gchar *assembler; /* compile command line template */ + 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 */ + GHashTable *commands; /* local commands */ + GCompletion *completions; /* command completion list */ + GSList *pre_hooks[HOOKNO_]; /* Pre-command hooks */ + GSList *post_hooks[HOOKNO_]; /* Post-command hooks */ + GSList *global_pre; /* global pre-command hook */ + GSList *global_post; /* global post-command hook */ + mix_config_t *config; /* externally provided configuration */ + mix_predicate_t *preds[PRNO_]; /* predicates for conditional breakpoints */ + GHashTable *mem_preds; /* predicates for memory conditional bps */ + gboolean log_msg; /* message logging activation flag*/ +}; + +extern void +log_message_ (mix_vm_cmd_dispatcher_t *dis, const gchar *fmt, ...); + +extern void +log_error_ (mix_vm_cmd_dispatcher_t *dis, const gchar *fmt, ...); + +#define wants_logs_(dis) (dis)->log_msg + +#endif /* XMIX_VM_COMMAND_H */ + diff --git a/mixlib/xmix_vm_handlers.c b/mixlib/xmix_vm_handlers.c new file mode 100644 index 0000000..ba7052b --- /dev/null +++ b/mixlib/xmix_vm_handlers.c @@ -0,0 +1,1387 @@ +/* -*-c-*- -------------- xmix_vm_handlers.c : + * Implementation of the functions declared in xmix_vm_handlers.h + * ------------------------------------------------------------------ + * $Id: xmix_vm_handlers.c,v 1.10 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "xmix_vm_handlers.h" + +/* available commands (in the same order as the type enum) */ +mix_vm_command_info_t commands_[] = { + { "help", cmd_help_, N_("Display this text"), "help [COMMAND]"}, + { "load", cmd_load_, N_("Load a MIX code file"), "load FILENAME"}, + { "edit", cmd_edit_, N_("Edit a MIXAL source file"), "edit [FILENAME]"}, + { "pedit", cmd_pedit_, N_("Print the external editor command"), "pedit"}, + { "sedit", cmd_sedit_, N_("Set the external editor command"), + "sedit COMMAND (e.g. emacs %s)"}, + { "compile", cmd_compile_, N_("Compile a MIXAL source file"), + "compile [FILENAME]"}, + { "pasm", cmd_pasm_, N_("Print the compile command"), "pasm"}, + { "sasm", cmd_sasm_, N_("Set the compile command"), + "sasm COMMAND (e.g. mixasm -g -l %s)"}, + { "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]"}, + { "pstat", cmd_pstat_, N_("Print current vm status"), "pstat"}, + { "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"), + "sreg 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"}, + { "sbpr", cmd_sbpr_, N_("Set conditional breakpoint on register change"), + "sbpr A | X | J | I[1-6]"}, + { "cbpr", cmd_cbpr_, N_("Clear conditional breakpoint on register change"), + "sbpr A | X | J | I[1-6]"}, + { "sbpm", cmd_sbpm_, N_("Set conditional breakpoint on mem cell change"), + "sbpm ADDRESS"}, + { "cbpm", cmd_cbpm_, N_("Clear conditional breakpoint on mem cell change"), + "cbpm ADDRESS"}, + { "sbpc", cmd_sbpc_, + N_("Set conditional breakpoint on comparison flag change"), "sbpc"}, + { "cbpc", cmd_cbpc_, + N_("Clear conditional breakpoint on comparison flag change"), "cbpc"}, + { "sbpo", cmd_sbpo_, + N_("Set conditional breakpoint on overflow toggled"), "sbpo"}, + { "cbpo", cmd_cbpo_, + N_("Set conditional breakpoint on overflow toggled"), "cbpo"}, + { "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"}, + { "strace", cmd_strace_, N_("Turn on/off instruction tracing"), + "strace on|off"}, + { "pbt", cmd_pbt_, N_("Print backtrace of executed instructions"), + "pbt [INS_NO] (e.g pbt 5)"}, + { "stime", cmd_stime_, N_("Turn on/off timing statistics"), + "stime on|off"}, + { "ptime", cmd_ptime_, N_("Print current time statistics"), "ptime"}, + { "sddir", cmd_sddir_, N_("Set devices directory"),"sddir NEWDIR"}, + { "pddir", cmd_pddir_, N_("Print current devices directory"),"pddir"}, + { "slog", cmd_slog_, N_("Turn on/off message logging"), "slog on|off"}, + { "pprog", cmd_pprog_, N_("Print the current program path"), "pprog"}, + { "psrc", cmd_psrc_, N_("Print the current program source path"), "psrc"}, + { "pline", cmd_pline_, + N_("Print the current (or a given) program source line"), "pline [LINENO]"}, + { NULL, NULL, NULL, NULL}, +}; + +/* trace current instruction */ +static void +do_trace_ (mix_vm_cmd_dispatcher_t *dis, gboolean error) +{ + 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); + } + + if (!error) + log_message_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line); + else + log_error_ (dis, "%d: [%-15s]\t%s", (gint)loc, STRINS, line); +} + +static void +trace_ (mix_vm_cmd_dispatcher_t *dis) +{ + if (wants_logs_ (dis)) + { + do_trace_ (dis, FALSE); + } +} + +#define trace_error_(dis) do_trace_ (dis, TRUE) + +/* run a program tracing executed instructions */ +static int +run_and_trace_ (mix_vm_cmd_dispatcher_t *dis) +{ + int k = MIX_VM_RUNNING; + if (!dis->trace) + return mix_vm_run (dis->vm); + else while (k == MIX_VM_RUNNING) + { + 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 void +print_help_ (gpointer key, gpointer val, gpointer data) +{ + mix_vm_command_info_t *info = (mix_vm_command_info_t *)val; + if (info) + fprintf ((FILE *)data, "%-15s%s\n", info->name, info->doc); +} + +gboolean +cmd_help_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg) > 0) + { + int i; + mix_vm_command_info_t *info = + (mix_vm_command_info_t *)g_hash_table_lookup + (dis->commands, (gpointer)arg); + for (i = 0; info == NULL && commands_[i].name; i++) + if (!strcmp (commands_[i].name, arg)) info = commands_ + i; + if (info) + { + fprintf (dis->out , _("%-15s%s.\n%-15sUsage: %s\n"), + info->name, info->doc, "", info->usage); + return TRUE; + } + fprintf (dis->out, _("No commands match `%s'\n"), arg); + return FALSE; + } + else + { + int i = 0; + fprintf (dis->out, _("Possible commands are:\n")); + for (i = 0; commands_[i].name; ++i) + fprintf (dis->out, "%-15s%s\n", commands_[i].name, commands_[i].doc); + g_hash_table_foreach (dis->commands, print_help_, (gpointer)dis->out); + return TRUE; + } +} + +gboolean +cmd_load_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + errno = 0; + if (arg == NULL || *arg == '\0') + { + log_error_ (dis, _("Missing file name")); + 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) ) + { + log_error_ (dis, _("Cannot load %s: "), arg); + if ( errno == 0 ) + log_error_ (dis, _("Wrong file format")); + else + log_error_ (dis, "%s", strerror (errno)); + return FALSE; + } + + if (dis->program != arg) + { + if (dis->program) g_free (dis->program); + dis->program = mix_file_complete_name (arg, MIX_CODE_DEFEXT); + } + + mix_eval_set_symbols_from_table (dis->eval, + mix_vm_get_symbol_table (dis->vm)); + if (wants_logs_ (dis)) + log_message_ (dis, _("Program loaded. Start address: %d"), + mix_vm_get_prog_count (dis->vm)); + + dis->laptime = dis->progtime = 0; + return TRUE; +} + +gboolean +cmd_edit_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (dis->editor == NULL) + { + log_error_ (dis, _("Editor not specified (use sedit)")); + return FALSE; + } + if (!arg || *arg == '\0') arg = mix_vm_cmd_dispatcher_get_src_file_path (dis); + if (!arg) + { + log_error_ (dis, _("MIXAL source file path not found")); + return FALSE; + } + else + { + gchar *cmd = g_strdup_printf (dis->editor, arg); + if (wants_logs_ (dis)) log_message_ (dis, cmd); + system (cmd); + if (wants_logs_ (dis)) log_message_ (dis, _(" ...done")); + g_free (cmd); + return TRUE; + } +} + +gboolean +cmd_compile_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (dis->assembler == NULL) + { + log_error_ (dis, _("MIX assembler not specified (use sasm)")); + return FALSE; + } + if (!arg || *arg == '\0') arg = mix_vm_cmd_dispatcher_get_src_file_path (dis); + if (!arg) + { + log_error_ (dis, _("MIXAL source file path not found")); + return FALSE; + } + else + { + gchar *cmd = g_strdup_printf (dis->assembler, arg); + if (wants_logs_ (dis)) log_message_ (dis, cmd); + if (system (cmd) == EXIT_SUCCESS && wants_logs_ (dis)) + log_message_ (dis, _("Successful compilation")); + g_free (cmd); + return TRUE; + } +} + +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); + + if (wants_logs_ (dis)) log_message_ (dis, _("Running ...")); + + switch (run_and_trace_ (dis)) + { + case MIX_VM_HALT: + if (wants_logs_ (dis)) log_message_ (dis, _("... done")); + break; + case MIX_VM_BREAK: + if (wants_logs_ (dis)) + { + gulong line = mix_vm_get_break_lineno (dis->vm); + if (line != 0) + log_message_ + (dis, _("... stopped: breakpoint at line %ld (address %d)"), + line, mix_vm_get_prog_count (dis->vm)); + else + log_message_ (dis, _("... stopped: breakpoint at address %d"), + mix_vm_get_prog_count (dis->vm)); + } + break; + case MIX_VM_COND_BREAK: + if (wants_logs_ (dis)) + { + gulong line = mix_vm_get_break_lineno (dis->vm); + if (line != 0) + log_message_ (dis, _("... stopped: %s (line %ld, address %d)"), + mix_vm_get_last_breakpoint_message (dis->vm), + line, mix_vm_get_prog_count (dis->vm)); + else + log_message_ (dis, _("... stopped: %s (address %d)"), + mix_vm_get_last_breakpoint_message (dis->vm), + mix_vm_get_prog_count (dis->vm)); + } + break; + case MIX_VM_ERROR: + log_error_ (dis, _("%s:"), mix_vm_get_last_error_string (dis->vm)); + trace_error_ (dis); + break; + default: + g_assert_not_reached (); + break; + } + + if (wants_logs_ (dis)) print_time_ (dis); + + return TRUE; +} + +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') + { + log_error_ (dis, _("Invalid argument: %s"), arg); + 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) + { + if (wants_logs_ (dis)) + log_message_(dis, _("End of program reached at address %d"), + mix_vm_get_prog_count (dis->vm)); + break; + } + else if (k == MIX_VM_ERROR) + { + log_error_ (dis, _("%s:"), mix_vm_get_last_error_string (dis->vm)); + trace_error_ (dis); + break; + } + } + if (wants_logs_ (dis)) print_time_ (dis); + + return TRUE; +} + +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; +} + +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 ) + log_error_ (dis, _("Symbol table not available")); + else if (arg != NULL && *arg != '\0') + { + if ( mix_symbol_table_is_defined (table, arg) ) + { + mix_word_print_to_file (mix_symbol_table_value (table, arg), + NULL, dis->out); + 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, dis->out, TRUE); + result = TRUE; + } + + return result; +} + +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 ) + { + log_error_ (dis, _("Invalid I index: %d"), i); + return FALSE; + } + mix_dump_context_add_opt (dis->dump, opt[i]); + } + } + break; + default: + log_error_ (dis, _("Invalid argument: %s"), arg); + return FALSE; + } + mix_vm_dump (dis->vm, dis->dump); + return TRUE; +} + +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; +} + +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; +} + +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 ) + { + log_error_ (dis, _("Missing memory address")); + 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] == '-') + { + gchar *narg; + arg[i++] = '\0'; + begin = atol (arg); + narg = arg + i; + i = 0; + while (isdigit (narg[i])) + i++; + while (isspace (narg[i])) + i++; + if (narg[i] != '\0') + error = TRUE; + else + end = atol (narg); + } + else + error = TRUE; + + if (error) + { + log_error_ (dis, _("Invalid argument: %s"), arg); + } + else if ( end < begin || end > MIX_VM_CELL_NO - 1 ) + { + log_error_ (dis, _("Invalid range: %ld-%ld"), 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; +} + +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) + { + log_error_ (dis, _("Invalid argument: %s"), arg); + } + + return ok; +} + +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) + { + log_error_ (dis, _("Invalid argument: %s"), arg); + } + + return ok; +} + +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) + { + log_error_ (dis, _("Invalid argument: %s"), arg); + } + + return ok; +} + +gboolean +cmd_smem_ (mix_vm_cmd_dispatcher_t *dis, const gchar *carg) +{ + gboolean ok = (strlen (carg) > 2 && isdigit (carg[0])); + glong addr = -1; + glong value = 0; + 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 + { + log_error_ (dis, _("Invalid argument: %s"), arg); + } + if (arg) g_free (arg); + + return ok; +} + +gboolean +cmd_ssym_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gboolean result = FALSE; + if (arg == NULL || strlen(arg) == 0) + { + log_error_ (dis, _("Missing arguments")); + } + 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 + { + log_error_ (dis, _("Wrong argument number")); + } + g_free (a); + } + return result; +} + +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') + { + log_error_ (dis, _("Invalid argument: %s"), arg); + return FALSE; + } + lineno = atol (arg); + switch (k = mix_vm_set_breakpoint (dis->vm, lineno)) + { + case MIX_VM_BP_INV_LINE: + log_error_ (dis, _("Line number %ld too high"), lineno); + break; + case MIX_VM_BP_ERROR: + log_error_ (dis, _("Could not set breakpoint: internal error")); + break; + case MIX_VM_BP_NDEBUG: + log_error_ (dis, _("Could not set breakpoint: no debug info available"), + dis->err); + break; + default: + if (wants_logs_ (dis)) + log_message_ (dis, _("Breakpoint set at line %ld"), k); + return TRUE; + } + return FALSE; +} + +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') + { + log_error_ (dis, _("Invalid argument: %s"), arg); + return FALSE; + } + address = atol (arg); + switch (mix_vm_set_breakpoint_address (dis->vm, address)) + { + case MIX_VM_BP_INV_ADDRESS: + log_error_ (dis, _("Invalid address %ld"), address); + break; + case MIX_VM_BP_ERROR: + log_error_ (dis, _("Could not set breakpoint: internal error")); + break; + default: + if (wants_logs_ (dis)) + log_message_ (dis, _("Breakpoint set at address %ld"), address); + return TRUE; + } + return FALSE; +} + +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') + { + log_error_ (dis, _("Invalid argument: %s"), arg); + return FALSE; + } + lineno = atol (arg); + switch (mix_vm_clear_breakpoint (dis->vm, lineno)) + { + case MIX_VM_BP_INV_LINE: + log_error_ (dis, _("No breakpoint set at line %ld"), lineno); + break; + case MIX_VM_BP_ERROR: + log_error_ (dis, _("Could not set breakpoint: internal error")); + break; + case MIX_VM_BP_NDEBUG: + log_error_ (dis, _("No debug info available")); + break; + case MIX_VM_BP_OK: + if (wants_logs_ (dis)) + log_message_ (dis, _("Breakpoint cleared at line %ld"), lineno); + return TRUE; + default: + g_assert_not_reached (); + break; + } + return FALSE; +} + +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') + { + log_error_ (dis, _("Invalid argument: %s"), arg); + return FALSE; + } + address = atol (arg); + switch (mix_vm_clear_breakpoint_address (dis->vm, address)) + { + case MIX_VM_BP_INV_ADDRESS: + log_error_ (dis, _("Invalid address %ld"), address); + break; + case MIX_VM_BP_ERROR: + log_error_ (dis, _("Could not clear breakpoint: internal error")); + break; + default: + if (wants_logs_ (dis)) + log_message_ (dis, _("Breakpoint cleared at address %ld"), address); + return TRUE; + } + return FALSE; +} + + +gboolean +cmd_cabp_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (strlen (arg) != 0) + { + log_error_ (dis, _("Unexpected argument: %s"), arg); + return FALSE; + } + mix_vm_clear_all_breakpoints (dis->vm); + return TRUE; +} + +gboolean +cmd_weval_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if ( strlen (arg) == 0 ) + { + log_error_ (dis, _("Missing expression")); + 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; kerr); + fputc ('\n', dis->err); + for (k = 0; kerr); + 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; + } +} + +gboolean +cmd_w2d_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if ( strlen (arg) == 0 ) + { + log_error_ (dis, _("Missing expression")); + 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])) + { + log_error_ (dis, _("Incorrect byte specification: %s"), b); + success = FALSE; + b = NULL; + } + else + { + bytes[k++] = mix_byte_new (atoi (b)); + b = strtok (NULL, " \t"); + } + } + if (success) + { + if (strtok (NULL, "\t") != NULL) + { + log_error_ (dis, + _("The expression %s does not fit in a word"), 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; + } +} + +gboolean +cmd_strace_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + static const gchar *ON = "on"; + static const gchar *OFF = "off"; + if (!arg || !strlen (arg)) + { + log_error_ (dis, _("Missing argument")); + } + else if (!strcmp (arg, ON)) + { + dis->trace = TRUE; + if (dis->config) mix_config_update (dis->config, TRACING_KEY_, ON); + } + else if (!strcmp (arg, OFF)) + { + dis->trace = FALSE; + if (dis->config) mix_config_update (dis->config, TRACING_KEY_, OFF); + } + else + log_error_ (dis, _("Wrong argument: "), arg); + return TRUE; +} + +gboolean +cmd_stime_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + static const gchar *ON = "on"; + static const gchar *OFF = "off"; + if (!arg || !strlen (arg)) + { + log_error_ (dis, _("Missing argument")); + } + else if (!strcmp (arg, ON)) + { + dis->printtime = TRUE; + if (dis->config) mix_config_update (dis->config, TIMING_KEY_, ON); + } + else if (!strcmp (arg, OFF)) + { + dis->printtime = FALSE; + if (dis->config) mix_config_update (dis->config, TIMING_KEY_, OFF); + } + else + log_error_ (dis, _("Wrong argument: "), arg); + return TRUE; +} + +gboolean +cmd_ptime_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + print_time_ (dis); + return TRUE; +} + +gboolean +cmd_pedit_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + const gchar *ed = mix_vm_cmd_dispatcher_get_editor (dis); + if (dis) + fprintf (dis->out, _("Edit command: %s\n"), ed); + else + fprintf (dis->out, _("Edit command not set (use sedit)\n")); + return TRUE; +} + +gboolean +cmd_sedit_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (!arg || !strlen (arg)) + { + log_error_ (dis, _("Missing argument")); + return FALSE; + } + mix_vm_cmd_dispatcher_set_editor (dis, arg); + return TRUE; +} + +gboolean +cmd_pasm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + const gchar *ed = mix_vm_cmd_dispatcher_get_assembler (dis); + if (dis) + fprintf (dis->out, _("Compile command: %s\n"), ed); + else + fprintf (dis->out, _("Compile command not set (use sasm)\n")); + return TRUE; +} + +gboolean +cmd_sasm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (!arg || !strlen (arg)) + { + log_error_ (dis, _("Missing argument")); + return FALSE; + } + mix_vm_cmd_dispatcher_set_assembler (dis, arg); + return TRUE; +} + +gboolean +cmd_sddir_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (!arg || !strlen (arg)) log_error_ (dis, _("Missing argument")); + else if (mix_device_set_dir (arg) && dis->config) + mix_config_set_devices_dir (dis->config, arg); + return TRUE; +} + +gboolean +cmd_pddir_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + fprintf (dis->out, _("Device directory: %s\n"), mix_device_get_dir ()); + return TRUE; +} + +static const gint INVALID_REG_ = -2; + +static mix_predicate_type_t +get_reg_pred_ (const gchar *arg) +{ + mix_predicate_type_t pred = INVALID_REG_; + + switch (*arg) + { + case 'A': + pred = MIX_PRED_REG_A; + break; + case 'X': + pred = MIX_PRED_REG_X; + break; + case 'J': + pred = MIX_PRED_REG_J; + break; + case 'I': + { + if ( strlen (arg) == 2 ) + { + int i = arg[1] - '1'; + if (i >= 0 && i < 6) + pred = MIX_PRED_REG_I1 - 1 + i; + } + } + break; + default: + break; + } + return pred; +} + +gboolean +cmd_sbpr_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + mix_predicate_type_t pred = get_reg_pred_ (arg); + if (pred != INVALID_REG_) + { + mix_vm_set_conditional_breakpoint (dis->vm, dis->preds[pred]); + if (wants_logs_ (dis)) + log_message_ (dis, + _("Conditional breakpoint on r%s change set"), arg); + return TRUE; + } + else + { + log_error_ (dis, _("Invalid argument %s"), arg); + return FALSE; + } +} + +gboolean +cmd_cbpr_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + mix_predicate_type_t pred = get_reg_pred_ (arg); + if (pred != INVALID_REG_) + { + if (mix_vm_clear_conditional_breakpoint (dis->vm, dis->preds[pred])) + { + if (wants_logs_(dis)) + log_message_ (dis, + _("Conditional breakpoint on r%s change removed"), + arg); + } + else + log_error_ (dis, _("No breakpoint set on r%s change"), arg); + return TRUE; + } + else + { + log_error_ (dis, _("Invalid argument %s"), arg); + return FALSE; + } +} + +gboolean +cmd_sbpm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gint add = atoi (arg); + gpointer key, value; + if (add < 0 || add > MIX_VM_CELL_NO) + { + log_error_ (dis, _("Invalid memory address: %s"), arg); + return FALSE; + } + if (!g_hash_table_lookup_extended (dis->mem_preds, GINT_TO_POINTER (add), + &key, &value)) + { + mix_predicate_t *new_pred = mix_predicate_new (MIX_PRED_MEM); + mix_predicate_set_mem_address (new_pred, add); + g_hash_table_insert (dis->mem_preds, + GINT_TO_POINTER (add), (gpointer)new_pred); + mix_vm_set_conditional_breakpoint (dis->vm, new_pred); + } + if (wants_logs_ (dis)) + log_message_ (dis, _("Conditional breakpoint on mem cell no. %d set"), + add); + return TRUE; +} + +gboolean +cmd_cbpm_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gint add = atoi (arg); + gpointer key, value; + if (add < 0 || add > MIX_VM_CELL_NO) + { + log_error_ (dis, _("Invalid memory address: %s"), arg); + return FALSE; + } + if (g_hash_table_lookup_extended (dis->mem_preds, GINT_TO_POINTER (add), + &key, &value)) + { + g_hash_table_remove (dis->mem_preds, key); + mix_vm_clear_conditional_breakpoint (dis->vm, (mix_predicate_t *)value); + mix_predicate_delete ((mix_predicate_t *)value); + if (wants_logs_ (dis)) + log_message_ (dis, + _("Conditional breakpoint on mem cell no. %d removed"), + add); + } + else + { + log_error_ (dis, _("No conditional breakpoint set at address %d"), + add); + } + return TRUE; +} + +gboolean +cmd_sbpo_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + log_error_ (dis, _("Unexpected argument: %s"), arg); + else + { + mix_vm_set_conditional_breakpoint (dis->vm, dis->preds[MIX_PRED_OVER]); + if (wants_logs_ (dis)) + log_message_ (dis, + _("Conditional breakpoint on overflow toggled set")); + } + return TRUE; +} + +gboolean +cmd_cbpo_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + log_error_ (dis, _("Unexpected argument: %s"), arg); + else + { + if (mix_vm_clear_conditional_breakpoint + (dis->vm, dis->preds[MIX_PRED_OVER])) + { + if (wants_logs_ (dis)) + log_message_ + (dis, _("Conditional breakpoint on overflow toggled removed.")); + } + else + log_error_ (dis, _("No breakpoint set on overflow toggle")); + } + return TRUE; +} + +gboolean +cmd_sbpc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + log_error_ (dis, _("Unexpected argument: %s"), arg); + else + { + mix_vm_set_conditional_breakpoint (dis->vm, dis->preds[MIX_PRED_CMP]); + if (wants_logs_ (dis)) + log_message_ + (dis, _("Conditional breakpoint on comparison flag changed set")); + } + return TRUE; +} + +gboolean +cmd_cbpc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + if (arg && strlen (arg)) + log_error_ (dis, _("Unexpected argument: %s"), arg); + else + { + if (mix_vm_clear_conditional_breakpoint + (dis->vm, dis->preds[MIX_PRED_CMP])) + { + if (wants_logs_ (dis)) + log_message_ + (dis, + _("Conditional breakpoint on comparison flag changed removed.")); + } + else + log_error_ (dis, _("No breakpoint set on comparison flag change")); + } + return TRUE; +} + +gboolean +cmd_pbt_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + enum {SIZE = 256}; + static gchar BUFFER[SIZE]; + gint no = atoi (arg); + gint k = 0, address; + guint line; + const mix_src_file_t *file = mix_vm_get_src_file (dis->vm); + char *name = + file ? g_path_get_basename (mix_src_file_get_path (file)) : NULL; + + const GSList *add = mix_vm_get_backtrace (dis->vm); + while (add && (no == 0 || k < no)) + { + BUFFER[0] = '\0'; + address = GPOINTER_TO_INT (add->data); + line = mix_vm_get_address_lineno (dis->vm, address); + if (line && file) + { + int j = 0; + g_snprintf (BUFFER, SIZE, "%s", mix_src_file_get_line (file, line)); + while (!isspace (BUFFER[j])) j++; + BUFFER[j] = '\0'; + } + if (strlen (BUFFER) == 0) g_snprintf (BUFFER, SIZE, "%d", address); + fprintf (dis->out, "#%d\t%s\tin %s%s:%d\n", k, BUFFER, name, + MIX_SRC_DEFEXT, line); + ++k; + add = add->next; + } + return TRUE; +} + +gboolean +cmd_slog_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + static const gchar *ON = "on"; + static const gchar *OFF = "off"; + if (arg && !strcmp (arg, ON)) + { + dis->log_msg = TRUE; + if (dis->config) mix_config_update (dis->config, LOGGING_KEY_, ON); + } + else if (arg && !strcmp (arg, OFF)) + { + dis->log_msg = FALSE; + if (dis->config) mix_config_update (dis->config, LOGGING_KEY_, OFF); + } + else + log_error_ (dis, _("Wrong argument: "), arg); + return TRUE; +} + +gboolean +cmd_pprog_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + const gchar *path = mix_vm_cmd_dispatcher_get_program_path (dis); + fprintf (dis->out, path? path : _("No program currently loaded")); + fprintf (dis->out, "\n"); + return (path != NULL); +} + +gboolean +cmd_psrc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + const gchar *path = mix_vm_cmd_dispatcher_get_src_file_path (dis); + fprintf (dis->out, path? path : _("No program currently loaded\n")); + fprintf (dis->out, "\n"); + return (path != NULL); +} + +gboolean +cmd_pline_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + gulong line = 0; + const gchar *txt; + + if (arg && strlen (arg)) line = atoi (arg); + + if (line < 0) + { + log_error_ (dis, _("Invalid argument")); + return FALSE; + } + + if (line == 0) + line = mix_vm_cmd_dispatcher_get_src_file_lineno (dis); + + if (line == 0) + txt = "No such line (debug info not available)\n"; + else + txt = mix_vm_cmd_dispatcher_get_src_file_line (dis, line, FALSE); + + if (txt == NULL || strlen (txt) == 0) txt = "No such line\n"; + + fprintf (dis->out, "Line %ld: %s\n", line, txt); + + return TRUE; +} + +gboolean +cmd_pstat_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + static const gchar *MSGS[MIX_VM_EMPTY + 1] = { + N_("Error loading or executing file"), + N_("Execution stopped: breakpoint encountered"), + N_("Execution stopped: conditional breakpoint encountered"), + N_("Program successfully terminated"), + N_("Execution stopped"), + N_("Program successfully loaded"), + N_("No program loaded") + }; + mix_vm_status_t status = + mix_vm_get_run_status (mix_vm_cmd_dispatcher_get_vm (dis)); + fprintf (dis->out, "VM status: %s\n", MSGS[status]); + return TRUE; +} diff --git a/mixlib/xmix_vm_handlers.h b/mixlib/xmix_vm_handlers.h new file mode 100644 index 0000000..b3258f9 --- /dev/null +++ b/mixlib/xmix_vm_handlers.h @@ -0,0 +1,87 @@ +/* -*-c-*- ---------------- xmix_vm_handlers.h : + * mix_vm_cmd_dispatcher command handlers + * ------------------------------------------------------------------ + * $Id: xmix_vm_handlers.h,v 1.4 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef XMIX_VM_HANDLERS_H +#define XMIX_VM_HANDLERS_H + +#include "xmix_vm_command.h" + +/* command handlers */ +#define DEC_FUN(name) \ + extern gboolean 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 (strace_); +DEC_FUN (stime_); +DEC_FUN (ptime_); +DEC_FUN (edit_); +DEC_FUN (compile_); +DEC_FUN (pedit_); +DEC_FUN (sedit_); +DEC_FUN (pasm_); +DEC_FUN (sasm_); +DEC_FUN (pddir_); +DEC_FUN (sddir_); +DEC_FUN (sbpr_); +DEC_FUN (sbpm_); +DEC_FUN (sbpc_); +DEC_FUN (sbpo_); +DEC_FUN (cbpr_); +DEC_FUN (cbpm_); +DEC_FUN (cbpc_); +DEC_FUN (cbpo_); +DEC_FUN (pbt_); +DEC_FUN (slog_); +DEC_FUN (pprog_); +DEC_FUN (psrc_); +DEC_FUN (pline_); +DEC_FUN (pstat_); + +/* default command structure */ +extern mix_vm_command_info_t commands_[]; + + +#endif /* XMIX_VM_HANDLERS_H */ + diff --git a/mixutils/Makefile.am b/mixutils/Makefile.am new file mode 100644 index 0000000..7d899d6 --- /dev/null +++ b/mixutils/Makefile.am @@ -0,0 +1,27 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2000, 2001, 2002 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. + +# $Id: Makefile.am,v 1.9 2002/04/08 00:30:34 jao Exp $ + +if MAKE_GUILE +INCLUDES = -I$(includedir) -I$(top_srcdir) -DMAKE_GUILE +else +INCLUDES = -I$(includedir) -I$(top_srcdir) +endif + +LDADD = $(top_builddir)/mixlib/libmix.a $(top_builddir)/lib/libreplace.a \ + $(top_builddir)/mixguile/libmixguile.a $(INTLLIBS) + +bin_PROGRAMS = mixasm mixvm +mixasm_SOURCES = mixasm.c mixasm_comp.h mixasm_comp.c +mixvm_SOURCES = mixvm.c mixvm_loop.h 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..78f9f1f --- /dev/null +++ b/mixutils/mixasm.c @@ -0,0 +1,136 @@ +/* -*-c-*- -------------- mixasm.c: + * Main function of mixasm, the mix assembler + * ------------------------------------------------------------------ + * $Id: mixasm.c,v 1.9 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include + +#ifdef HAVE_GETOPT_LONG +# include +#else +# include +#endif /* HAVE_GETOPT_LONG */ + +#include "mixasm_comp.h" + +enum { + VER_OPT = 'v', + HELP_OPT = 'h', + USAGE_OPT = 'u', + OUT_OPT = 'o', + LIST_OPT = 'l', + NDEBUG_OPT = 'O' +}; + + +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}, + {"ndebug", no_argument, 0, NDEBUG_OPT}, + {0, 0, 0, 0} +}; + +static const gchar *USAGE_ = +N_("Usage: %s [-vhulO] [-o OUTPUT_FILE] [--version] [--help]\n" + "\t[--usage] [--ndebug] [--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 = TRUE; + + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + while (1) + { + /* -g option is still available, but is no longer used */ + c = getopt_long (argc, argv, "vhuo:lOg", 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: + mix_print_license ("mixasm, MIX assembler"); + return EXIT_SUCCESS; + case OUT_OPT: + out = optarg; + break; + case LIST_OPT: + use_list = TRUE; + list = optarg; + break; + case NDEBUG_OPT: + debug = FALSE; + break; + case 'g': + /* used to be the switch to create debug version, not needed anymore */ + 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..0bbf8a0 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#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..f6537f4 --- /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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXASM_COMP_H +#define MIXASM_COMP_H + +#include + +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..a0ae443 --- /dev/null +++ b/mixutils/mixvm.c @@ -0,0 +1,150 @@ +/* -*-c-*- -------------- mixvm.c : + * Main function for mixvm, the mix vm simulator + * ------------------------------------------------------------------ + * $Id: mixvm.c,v 1.10 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + +#include +#include +#include + +#include +#include + +#ifdef HAVE_GETOPT_LONG +# include +#else +# include +#endif /* HAVE_GETOPT_LONG */ + +#include "mixvm_loop.h" + +enum { + VER_OPT = 'v', + HELP_OPT = 'h', + USAGE_OPT = 'u', + RUN_OPT = 'r', + DUMP_OPT = 'd', + TIME_OPT = 't', + EMACS_OPT = 'e', /* used by mixvm-gud only */ + NOINIT_OPT = 'q' +}; + +static const char *options_ = "vhurdt"; /* 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}, + {"time", no_argument, 0, TIME_OPT}, + /* pek: yo! */ + {"emacs", no_argument, 0, EMACS_OPT}, + {"noinit", no_argument, 0, NOINIT_OPT}, + {0, 0, 0, 0} +}; + +static const gchar *USAGE_ = +N_("Usage: %s [-vhurdqt] [--version] [--help] [--noinit] [--usage]" + "\n\t[--run] [--dump] [--time] [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; + gboolean initfile = TRUE; + gboolean ptime = 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: + mix_print_license ("mixvm, MIX virtual machine"); + return EXIT_SUCCESS; + case RUN_OPT: + in = optarg; + run = TRUE; + break; + case DUMP_OPT: + dump = TRUE; + break; + case TIME_OPT: + ptime = 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; + case NOINIT_OPT: + initfile = FALSE; + 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, ptime); + else mix_vmloop (argc, argv, initfile, in, emacs); + + mix_release_lib (); + + return EXIT_SUCCESS; + +} + + + + diff --git a/mixutils/mixvm_command.c b/mixutils/mixvm_command.c new file mode 100644 index 0000000..0fbe1ce --- /dev/null +++ b/mixutils/mixvm_command.c @@ -0,0 +1,270 @@ +/* -*-c-*- -------------- mixvm_command.c : + * Implementation of the functions declared in mixvm_command.h + * ------------------------------------------------------------------ + * $Id: mixvm_command.c,v 1.12 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include +#include + +#include + +#ifdef HAVE_LIBREADLINE +# include +# include +# ifndef HAVE_RL_COMPLETION_MATCHES /* old versions of rl don't use rl_ */ +# define rl_completion_matches completion_matches +# endif +#else /* ! HAVE_LIBREADLINE */ + typedef int Function (); +#endif /* HAVE_LIBREADLINE */ + +#include +#include +#include +#include +#include + +#ifdef MAKE_GUILE +# include +static gboolean +try_guile_ (char *line) +{ + if (line[0] == '(') + { + if (line[strlen (line) -1] != ')') return FALSE; + mixguile_interpret_command (line); + return TRUE; + } + return FALSE; +} +#else /* !MAKE_GUILE */ +# define try_guile_(ignored) FALSE +#endif /* MAKE_GUILE */ + +#include "mixvm_loop.h" +#include "mixvm_command.h" + +/* mixvm dispatcher */ +static mix_vm_cmd_dispatcher_t *dis_ = NULL; +static mix_config_t *config_ = NULL; + +/* The names of functions that actually do the manipulation. */ +#define DEC_FUN(name) \ +static gboolean cmd_##name (mix_vm_cmd_dispatcher_t *dis, const char *arg) + +DEC_FUN (shell_); +DEC_FUN (quit_); +DEC_FUN (prompt_); + +mix_vm_command_info_t commands[] = { + { "prompt", cmd_prompt_, N_("Set command prompt"), "prompt PROMPT" }, + { "shell", cmd_shell_, N_("Execute shell command"), "shell COMMAND" }, + { "quit", cmd_quit_, N_("Quit the program"), "quit" }, + { (char *)NULL, (Function *)NULL, (char *)NULL } +}; + + +#ifdef HAVE_LIBREADLINE +/* readline functions */ +static char * +mixvm_cmd_generator_ (const 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 = rl_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_ (const char *text, int state) +{ + static const GList *comp = NULL; + char *prefix = NULL; + char *name = NULL; + + /* If this is a new word to complete, initialize now. */ + if (!state) + { + if (prefix) g_free (prefix); + comp = mix_vm_cmd_dispatcher_complete (dis_, text, &prefix); + } + + /* Return the next name which partially matches from the command list. */ + if (comp) + { + name = g_strdup ((const gchar *)comp->data); + comp = comp->next; + } + + return name; +} +#endif /* HAVE_LIBREADLINE */ + + +/* 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_quit_ (mix_vm_cmd_dispatcher_t *dis, const char *arg) +{ + puts (_("Quitting ...")); + if (dis_) mix_vm_cmd_dispatcher_delete (dis_); + if (config_) mix_config_delete (config_); + exit (0); + + /* pek: anything needed here to make the marker disappear??? */ + return FALSE; +} + +static int +cmd_shell_ (mix_vm_cmd_dispatcher_t *dis, const char *arg) +{ + system (arg); + return TRUE; +} + +static int +cmd_prompt_ (mix_vm_cmd_dispatcher_t *dis, const char *arg) +{ + if (arg && strlen (arg)) mix_vmloop_set_prompt (arg); + return TRUE; +} + + +/* external interface */ +static void +init_dis_ (mix_vm_cmd_dispatcher_t *dis) +{ + static const gchar * envars[] = { "MDK_EDITOR", "X_EDITOR", "EDITOR", + "VISUAL" }; + + static const guint s = sizeof (envars) / sizeof (envars[0]); + static const gchar *editor = NULL; + gchar *edit = NULL; + + if (!editor) + { + int k; + for (k = 0; k < s; k++) + if ( (editor = getenv (envars[k])) != NULL ) break; + } + if (!editor) editor = "vi"; + edit = g_strconcat (editor, " %s", NULL); + mix_vm_cmd_dispatcher_set_editor (dis, edit); + g_free (edit); + mix_vm_cmd_dispatcher_set_assembler (dis, "mixasm %s"); +} + +mix_vm_cmd_dispatcher_t * +mixvm_cmd_init (mix_config_t *config, char *arg, gboolean use_emacs) +{ + int k; + +#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 */ + config_ = config; + dis_ = mix_vm_cmd_dispatcher_new_with_config (stdout, stderr, config_); + + if ( dis_ == NULL) + g_error (_("Failed initialisation (no memory resources)")); + + init_dis_ (dis_); + + /* add local commands */ + k = 0; + while (commands[k].name) + { + mix_vm_cmd_dispatcher_register_new (dis_, commands + k); + ++k; + } + + /* 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); + + return dis_; +} + +gboolean +mixvm_cmd_exec (char *line) +{ + if (!line) return cmd_quit_(dis_, NULL); + + /* strip white space */ + line = g_strstrip(line); + + if (strlen (line) == 0) return TRUE; + + if (try_guile_ (line)) return TRUE; + + (void)mix_vm_cmd_dispatcher_dispatch_text (dis_, line); + + return TRUE; +} diff --git a/mixutils/mixvm_command.h b/mixutils/mixvm_command.h new file mode 100644 index 0000000..28ff877 --- /dev/null +++ b/mixutils/mixvm_command.h @@ -0,0 +1,38 @@ +/* -*-c-*- ---------------- mixvm_command.h : + * Declarations for commands accepted by the mix virtual machine + * ------------------------------------------------------------------ + * $Id: mixvm_command.h,v 1.5 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXVM_COMMAND_H +#define MIXVM_COMMAND_H + +#include +#include + +extern mix_vm_cmd_dispatcher_t * +mixvm_cmd_init (mix_config_t *config, 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..ef84444 --- /dev/null +++ b/mixutils/mixvm_loop.c @@ -0,0 +1,160 @@ +/* -*-c-*- -------------- mixvm_loop.c : + * Implementation of mix vm command loop. + * ------------------------------------------------------------------ + * $Id: mixvm_loop.c,v 1.15 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef MAKE_GUILE +#include +#endif + +#include "mixvm_command.h" +#include "mixvm_loop.h" + +#ifdef HAVE_LIBHISTORY +# include +#else +# define add_history(x) ((void)0) +#endif + +#ifdef HAVE_LIBREADLINE +# include +#else /* !HAVE_LIBREADLINE */ +static char * +readline (char *prompt) +{ + enum {LINE_LEN = 256}; + char *line = g_new (char, LINE_LEN); + printf ("%s", prompt); + return fgets (line, LINE_LEN, stdin); +} +#endif /* HAVE_LIBREADLINE */ + +/* A static variable for holding the line. */ +static char *line_read = (char *)NULL; + +#define PROMPT_LEN 128 +static char PROMPT[PROMPT_LEN + 1] = {'M', 'I', 'X', ' ', '>'}; +static const char *CONFIG_FILE_ = "mixvm.config"; +static const char *PROMPT_KEY_ = "Prompt"; + +/* 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 */ +static mix_config_t *config_ = NULL; + +static mix_vm_cmd_dispatcher_t * +init_mixvm_ (const gchar *file, gboolean use_emacs) +{ + static const gchar *HISTORY_FILE = "mixvm.history"; + static gint HISTORY_SIZE = 100; + config_ = mix_config_new (NULL, CONFIG_FILE_); + + mix_config_set_autosave (config_, TRUE); + if (!mix_config_get_history_file (config_)) + mix_config_set_history_file (config_, HISTORY_FILE); + if (mix_config_get_history_size (config_) == 0) + mix_config_set_history_size (config_, HISTORY_SIZE); + + mix_vmloop_set_prompt (mix_config_get (config_, PROMPT_KEY_)); + + return mixvm_cmd_init (config_, (char *)file, use_emacs); +} + +void +mix_vmloop_set_prompt (const gchar *prompt) +{ + if (prompt) + { + g_snprintf (PROMPT, PROMPT_LEN, "%s ", prompt); + mix_config_update (config_, PROMPT_KEY_, prompt); + } +} + +static void +loop_ (int argc, char *argv[]) +{ + while ( mixvm_cmd_exec (rl_gets ()) ) + ; + mix_config_delete (config_); +} + +void +mix_vmloop (int argc, char *argv[], gboolean initfile, + const gchar *file, gboolean use_emacs) +{ +#ifdef MAKE_GUILE + mix_vm_cmd_dispatcher_t *dis = init_mixvm_ (file, use_emacs); + mixguile_init (argc, argv, initfile, loop_, dis); +#else + (void) init_mixvm_ (file, use_emacs); + loop_ (argc, argv); +#endif +} + +/* run a program and exit */ +void +mix_vmrun (const gchar *code_file, gboolean dump, gboolean ptime) +{ + gchar *time_cmd = ptime? g_strdup ("stime on") : g_strdup ("stime off"); + gchar *run_cmd = g_strdup ("run"); + gchar *dump_cmd = dump? g_strdup ("pall") : NULL; + gboolean result; + + init_mixvm_ (code_file, FALSE); + result = mixvm_cmd_exec (time_cmd) && mixvm_cmd_exec (run_cmd); + if (result && dump) mixvm_cmd_exec (dump_cmd); + mix_config_set_autosave (config_, FALSE); + mix_config_delete (config_); + g_free(time_cmd); + g_free(run_cmd); + if (dump_cmd) g_free(dump_cmd); +} diff --git a/mixutils/mixvm_loop.h b/mixutils/mixvm_loop.h new file mode 100644 index 0000000..2dabfcd --- /dev/null +++ b/mixutils/mixvm_loop.h @@ -0,0 +1,38 @@ +/* -*-c-*- ---------------- mixvm_loop.h : + * Declarations for functions controlling the mixvm loop. + * ------------------------------------------------------------------ + * $Id: mixvm_loop.h,v 1.2 2005/09/20 19:43:13 jao Exp $ + * ------------------------------------------------------------------ + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef MIXVM_LOOP_H +#define MIXVM_LOOP_H + +extern void +mix_vmloop (int argc, char *argv[], gboolean initfile, + const gchar *code_file, gboolean use_emacs); + +extern void +mix_vmrun (const gchar *code_file, gboolean dump, gboolean ptime); + +extern void +mix_vmloop_set_prompt (const gchar *prompt); + +#endif /* MIXVM_LOOP_H */ diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..be63e78 --- /dev/null +++ b/po/ChangeLog @@ -0,0 +1,143 @@ +2004-07-30 Jose Antonio Ortega Ruiz + + * de.po (Module): mike's german translation. + +2002-03-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.40. + * cat-id-tbl.c: Remove file. + * stamp-cat-id: Remove file. + +2001-09-26 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-27 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-26 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-25 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-25 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-25 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-23 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-21 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-17 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-17 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-07-23 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-23 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-23 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-23 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-18 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize + + * Makefile.in.in: Upgrade to gettext-0.10.38. + * cat-id-tbl.c: Remove file. + * stamp-cat-id: Remove file. + +2000-02-08 jose antonio ortega ruiz + + * ca.po: New file diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..f171d41 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +# Set of available translations +de diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 0000000..8b09f53 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,25 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Free Software Foundation, Inc. + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..c8a1a0a --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,27 @@ +# 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.c +mixlib/mix_config.c +mixlib/mix_parser.c +mixlib/mix_predicate.c +mixlib/mix_vm_dump.c +mixlib/mix_vm_command.c +mixlib/mix_eval.c +mixlib/xmix_vm_handlers.c + +mixgtk/mixgtk_device.c +mixgtk/mixgtk_gen_handlers.c +mixgtk/mixgtk_mixal.c +mixgtk/mixgtk_mixvm.c +mixgtk/gmixvm.c +mixgtk/mixgtk.c +mixgtk/mixgtk.glade + +mixguile/mixguile.c +mixguile/mixguile_cmd_dispatcher.c + diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..3df6691 --- /dev/null +++ b/po/de.po @@ -0,0 +1,1553 @@ +# German translation for GNU MDK. +# Copyright (C) 2000-2005 Free Software Foundation, Inc. +# This file is distributed under the same license as the GNU MDK package. +# Michael Scholz , 2003-2004 +# +msgid "" +msgstr "" +"Project-Id-Version: GNU MDK 1.2.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2004-08-02 10:21+0200\n" +"PO-Revision-Date: 2005-09-19 22:56+0200\n" +"Last-Translator: Michael Scholz \n" +"Language-Team: German (no team)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: mixutils/mixasm.c:59 +#, c-format +msgid "" +"Usage: %s [-vhulO] [-o OUTPUT_FILE] [--version] [--help]\n" +"\t[--usage] [--ndebug] [--output=OUTPUT_FILE] [--list[=LIST_FILE]] file\n" +msgstr "" +"Aufruf: %s [-vhulO] [-o OUTPUT_FILE] [--version] [--help]\n" +"\t[--usage] [--ndebug] [--output=OUTPUT_FILE] [--list[=LIST_FILE]] file\n" + +#: mixutils/mixasm.c:103 mixutils/mixvm.c:116 +#, c-format +msgid "(Try: %s -h)\n" +msgstr "(Versuche: %s -h)\n" + +#: mixutils/mixasm.c:112 +#, c-format +msgid "*** Error: Missing source file.\n" +msgstr "*** Fehler: Quelldatei fehlt.\n" + +#: mixutils/mixasm.c:117 mixutils/mixvm.c:131 +#, c-format +msgid "*** Error: Too many input files.\n" +msgstr "*** Fehler: Zu viele Eingabedateien.\n" + +#: mixutils/mixasm_comp.c:38 +#, c-format +msgid "*** Unable to open source file %s\n" +msgstr "*** Kann Quelldatei %s nicht öffnen\n" + +#: mixutils/mixasm_comp.c:45 +#, c-format +msgid "(%d warning(s))\n" +msgstr "(%d Warnung(en))\n" + +#: mixutils/mixasm_comp.c:48 +#, c-format +msgid "*** Error writing output code file: %s\n" +msgstr "*** Fehler beim Schreiben der Ausgabedatei: %s\n" + +#: mixutils/mixasm_comp.c:56 +#, c-format +msgid "*** Error writing listing file: %s\n" +msgstr "*** Fehler beim Schreiben der Listingdatei: %s\n" + +#: mixutils/mixasm_comp.c:63 +#, c-format +msgid "(%d warning(s), %d error(s))\n" +msgstr "(%d Warnungen, %d Fehler)\n" + +#: mixutils/mixvm.c:69 +#, c-format +msgid "" +"Usage: %s [-vhurdqt] [--version] [--help] [--noinit] [--usage]\n" +"\t[--run] [--dump] [--time] [MIX_FILE]\n" +msgstr "" +"Aufruf: %s [-vhurdqt] [--version] [--help] [--noinit] [--usage]\n" +"\t[--run] [--dump] [--time] [MIX_FILE]\n" + +#: mixutils/mixvm_command.c:81 +msgid "Set command prompt" +msgstr "Kommandoprompt setzen" + +#: mixutils/mixvm_command.c:82 +msgid "Execute shell command" +msgstr "Shellkommando ausführen" + +#: mixutils/mixvm_command.c:83 +msgid "Quit the program" +msgstr "Programm beenden" + +#: mixutils/mixvm_command.c:166 +msgid "Quitting ..." +msgstr "Beenden ..." + +#: mixutils/mixvm_command.c:229 +msgid "Failed initialisation (no memory resources)" +msgstr "Initialisierungsfehler (keine Speicherressourcen)" + +#: mixlib/mix.c:66 +#, c-format +msgid "" +"%s (GNU MDK %s)\n" +"\n" +msgstr "" +"%s (GNU MDK %s)\n" +"\n" + +#: mixlib/mix.c:84 +#, c-format +msgid "Error creating %s dir %s: %s" +msgstr "Fehler beim Erzeugen von %s, Verzeichnis %s: %s" + +#: mixlib/mix.c:93 +#, c-format +msgid "Error setting %s dir: %s is not a directory" +msgstr "Fehler beim Setzen von %s: %s ist kein Verzeichnis" + +#: mixlib/mix_config.c:216 +#, c-format +msgid "Unable to open config file %s (%s)" +msgstr "Kann Konfigurationsdatei nicht öffnen %s (%s)" + +#: mixlib/mix_parser.c:37 +msgid "successful compilation" +msgstr "Kompilation erfolgreich" + +#: mixlib/mix_parser.c:38 +msgid "file not yet compiled" +msgstr "Datei ist noch nicht kompiliert" + +#: mixlib/mix_parser.c:39 +msgid "internal error" +msgstr "Interner Fehler" + +#: mixlib/mix_parser.c:40 +msgid "unable to open MIX source file" +msgstr "kann MIX-Quelldatei nicht öffnen" + +#: mixlib/mix_parser.c:41 +msgid "unable to open MIX output file" +msgstr "kann MIX-Ausgabedatei nicht öffnen" + +#: mixlib/mix_parser.c:42 +msgid "unexpected end of file" +msgstr "unerwartetes Dateiende" + +#: mixlib/mix_parser.c:43 +msgid "invalid location field" +msgstr "ungültiges Location-Feld" + +#: mixlib/mix_parser.c:44 +msgid "duplicated symbol" +msgstr "Symbol ist doppelt" + +#: mixlib/mix_parser.c:45 +msgid "symbol too long" +msgstr "Symbol ist zu lang" + +#: mixlib/mix_parser.c:46 +msgid "missing operator field" +msgstr "Operator-Feld fehlt" + +#: mixlib/mix_parser.c:47 +msgid "unexpected location symbol" +msgstr "unerwartetes Location-Symbol" + +#: mixlib/mix_parser.c:48 +msgid "invalid address field" +msgstr "ungültiges Adreßfeld" + +#: mixlib/mix_parser.c:49 +msgid "invalid index field" +msgstr "ungültiges Index-Feld" + +#: mixlib/mix_parser.c:50 +msgid "invalid f-specification" +msgstr "ungültige F-Spezifikation" + +#: mixlib/mix_parser.c:51 +msgid "invalid operation field" +msgstr "ungültiges Operation-Feld" + +#: mixlib/mix_parser.c:52 +msgid "invalid expression" +msgstr "ungültiger Ausdruck" + +#: mixlib/mix_parser.c:53 +msgid "undefined symbol" +msgstr "Symbol nicht definiert" + +#: mixlib/mix_parser.c:54 +msgid "mismatched parenthesis" +msgstr "Klammerfehler" + +#: mixlib/mix_parser.c:55 +msgid "unexpected f-specfication" +msgstr "unerwartete F-Spezifikation" + +#: mixlib/mix_parser.c:56 +msgid "missing symbol name" +msgstr "Symbolname fehlt" + +#: mixlib/mix_parser.c:57 +msgid "symbol is an instruction name" +msgstr "Symbol ist ein Instruktionsname" + +#: mixlib/mix_parser.c:58 +msgid "failed write access to code file" +msgstr "kein Schreibzugriff auf Code-Datei" + +#: mixlib/mix_parser.c:59 +msgid "operand of ALF pseudo instruction has less than 5 chars" +msgstr "Operand von ALF-Pseudoinstruktion hat weniger als 5 Zeichen" + +#: mixlib/mix_parser.c:60 +msgid "operand of ALF pseudo instruction has more than 5 chars" +msgstr "Operand von ALF-Pseudoinstruktion hat mehr als 5 Zeichen" + +#: mixlib/mix_parser.c:61 +msgid "operand of ALF pseudo instruction must be quoted" +msgstr "Operand von ALF-Pseudoinstruktion muß in Anführungszeichen" + +#: mixlib/mix_parser.c:136 +msgid "No system resources" +msgstr "Keine Systemressourcen" + +#: mixlib/mix_parser.c:381 +#, c-format +msgid "\t%s\n" +msgstr "\t%s\n" + +#: mixlib/mix_parser.c:381 +msgid "UNKNOWN" +msgstr "UNBEKANNT" + +#: mixlib/mix_parser.c:406 +#, c-format +msgid "" +"*** %s%s: compilation summary ***\n" +"\n" +msgstr "" +"*** %s%s: Kompilerzusammenfassung ***\n" +"\n" + +#: mixlib/mix_parser.c:410 +msgid "Src Address Compiled word Symbolic rep\n" +msgstr "Src Address Compiled word Symbolic rep\n" + +#: mixlib/mix_parser.c:415 +#, c-format +msgid "" +"\n" +"*** Start address:\t%d\n" +"*** End address:\t%d\n" +msgstr "" +"\n" +"*** Startadresse:\t%d\n" +"*** Endadresse:\t%d\n" + +#: mixlib/mix_parser.c:418 +#, c-format +msgid "" +"\n" +"*** Symbol table\n" +msgstr "" +"\n" +"*** Symboltabelle\n" + +#: mixlib/mix_parser.c:421 +#, c-format +msgid "" +"\n" +"*** End of summary ***\n" +msgstr "" +"\n" +"*** Ende der Zusammenfassung ***\n" + +#: mixlib/mix_parser.c:598 +msgid "warning" +msgstr "Warnung" + +#: mixlib/mix_parser.c:598 +msgid "error" +msgstr "Fehler" + +#: mixlib/mix_predicate.c:176 +#, c-format +msgid "Register A changed to %s%ld" +msgstr "Register A geändert zu %s%ld" + +#: mixlib/mix_predicate.c:181 +#, c-format +msgid "Register X changed to %s%ld" +msgstr "Register X geändert zu %s%ld" + +#: mixlib/mix_predicate.c:186 +#, c-format +msgid "Register J changed to %d" +msgstr "Register J geändert zu %d" + +#: mixlib/mix_predicate.c:191 +#, c-format +msgid "Register I%d changed to %s%d" +msgstr "Register I%d geändert zu %s%d" + +#: mixlib/mix_predicate.c:197 +#, c-format +msgid "Comparison flag changed to %s" +msgstr "Comparision Flag geändert zu %s" + +#: mixlib/mix_predicate.c:201 +#, c-format +msgid "Overflow toggled %s" +msgstr "Overflow gewechselt zu %s" + +#: mixlib/mix_predicate.c:205 +#, c-format +msgid "Memory address %d changed to %s%ld" +msgstr "Speicheradresse %d geändert zu %s%ld" + +#: mixlib/mix_vm_dump.c:113 +#, c-format +msgid "Overflow: %s\n" +msgstr "Overflow: %s\n" + +#: mixlib/mix_vm_dump.c:134 +#, c-format +msgid "Cmp: %s\n" +msgstr "Cmp: %s\n" + +#: mixlib/mix_vm_command.c:480 +#, c-format +msgid "Unknown command. Try: help\n" +msgstr "Unbekanntes Kommando. Versuche: help\n" + +#: mixlib/mix_eval.c:29 +msgid "Successful evaluation" +msgstr "Erfolgreiche Berechnung" + +#: mixlib/mix_eval.c:30 +msgid "Syntax error in expression" +msgstr "Syntaxfehler im Ausdruck" + +#: mixlib/mix_eval.c:31 +msgid "Out of range F-specification" +msgstr "Außerhalb des Bereiches F-Spezifikation" + +#: mixlib/mix_eval.c:32 +msgid "Mismatched parenthesis" +msgstr "Klammerfehler" + +#: mixlib/mix_eval.c:33 +msgid "Undefined symbol" +msgstr "Undefiniertes Symbol" + +#: mixlib/mix_eval.c:34 +msgid "Internal error" +msgstr "Interner Fehler" + +#: mixlib/xmix_vm_handlers.c:29 +msgid "Display this text" +msgstr "Zeigt diesen Text" + +#: mixlib/xmix_vm_handlers.c:30 +msgid "Load a MIX code file" +msgstr "Eine MIX-Datei laden" + +#: mixlib/xmix_vm_handlers.c:31 mixgtk/mixgtk.glade:68 +msgid "Edit a MIXAL source file" +msgstr "Eine MIXAL-Quelldatei bearbeiten" + +#: mixlib/xmix_vm_handlers.c:32 +msgid "Print the external editor command" +msgstr "Externen Editor ausgeben" + +#: mixlib/xmix_vm_handlers.c:33 +msgid "Set the external editor command" +msgstr "Externen Editor setzen" + +#: mixlib/xmix_vm_handlers.c:35 mixgtk/mixgtk.glade:91 +msgid "Compile a MIXAL source file" +msgstr "Eine MIXAL-Quelldatei kompilieren" + +#: mixlib/xmix_vm_handlers.c:37 +msgid "Print the compile command" +msgstr "Kompilerkommando ausgeben" + +#: mixlib/xmix_vm_handlers.c:38 +msgid "Set the compile command" +msgstr "Kompilerkommando setzen" + +#: mixlib/xmix_vm_handlers.c:40 +msgid "Run loaded or given MIX code file" +msgstr "Starte geladene oder angegebene MIX-Datei" + +#: mixlib/xmix_vm_handlers.c:42 +msgid "Execute next instruction(s)" +msgstr "Nächste Instruktion(en) ausführen" + +#: mixlib/xmix_vm_handlers.c:44 +msgid "Print current vm status" +msgstr "Aktuellen VM-Status anzeigen" + +#: mixlib/xmix_vm_handlers.c:45 +msgid "Print program counter value" +msgstr "Programm-Zählerwert anzeigen" + +#: mixlib/xmix_vm_handlers.c:46 +msgid "Print symbol value" +msgstr "Symbolwert anzeigen" + +#: mixlib/xmix_vm_handlers.c:47 +msgid "Print register value" +msgstr "Registerwert anzeigen" + +#: mixlib/xmix_vm_handlers.c:49 +msgid "Print comparison and overflow flags" +msgstr "Comparison- und Overflow-Flag anzeigen" + +#: mixlib/xmix_vm_handlers.c:51 +msgid "Print all registers and flags" +msgstr "Alle Register und Flags anzeigen" + +#: mixlib/xmix_vm_handlers.c:52 +msgid "Print memory contents in address range" +msgstr "Speicherinhalt im Adreßbereich anzeigen" + +#: mixlib/xmix_vm_handlers.c:54 +msgid "Set register value" +msgstr "Registerwert setzen" + +#: mixlib/xmix_vm_handlers.c:56 +msgid "Set comparison flag value" +msgstr "Comparison-Flag setzen" + +#: mixlib/xmix_vm_handlers.c:57 +msgid "Set overflow flag value" +msgstr "Overflow-Flag setzen" + +#: mixlib/xmix_vm_handlers.c:58 +msgid "Set memory contents in given address" +msgstr "Speicherinhalt in angegebener Adresse setzen" + +#: mixlib/xmix_vm_handlers.c:60 +msgid "Set a symbol's value" +msgstr "Einen Symbolwert setzen" + +#: mixlib/xmix_vm_handlers.c:61 +msgid "Set break point at given line" +msgstr "Breakpoint bei angegebener Zeile setzen" + +#: mixlib/xmix_vm_handlers.c:62 +msgid "Clear break point at given line" +msgstr "Breakpoint bei angegebener Zeile löschen" + +#: mixlib/xmix_vm_handlers.c:63 +msgid "Set break point at given address" +msgstr "Breakpoint bei angegebener Adresse setzen" + +#: mixlib/xmix_vm_handlers.c:65 +msgid "Clear break point at given address" +msgstr "Breakpoint bei angegebener Adresse löschen" + +#: mixlib/xmix_vm_handlers.c:67 +msgid "Set conditional breakpoint on register change" +msgstr "Conditional Breakpoint bei Registeränderung setzen" + +#: mixlib/xmix_vm_handlers.c:69 +msgid "Clear conditional breakpoint on register change" +msgstr "Conditional Breakpoint bei Registeränderung löschen" + +#: mixlib/xmix_vm_handlers.c:71 +msgid "Set conditional breakpoint on mem cell change" +msgstr "Conditional Breakpoint bei Speicherzellenänderung setzen" + +#: mixlib/xmix_vm_handlers.c:73 +msgid "Clear conditional breakpoint on mem cell change" +msgstr "Conditional Breakpoint bei Speicherzellenänderung löschen" + +#: mixlib/xmix_vm_handlers.c:76 +msgid "Set conditional breakpoint on comparison flag change" +msgstr "Conditional Breakpoint bei Comparison-Flag-Änderung setzen" + +#: mixlib/xmix_vm_handlers.c:78 +msgid "Clear conditional breakpoint on comparison flag change" +msgstr "Conditional Breakpoint bei Comparison-Flag-Änderung löschen" + +#: mixlib/xmix_vm_handlers.c:80 mixlib/xmix_vm_handlers.c:82 +msgid "Set conditional breakpoint on overflow toggled" +msgstr "Conditional Breakpoint bei Overflow-Änderung setzen" + +#: mixlib/xmix_vm_handlers.c:83 +msgid "Clear all breakpoints" +msgstr "Alle Breakpoints löschen" + +#: mixlib/xmix_vm_handlers.c:84 +msgid "Evaluate a given W-expression" +msgstr "W-Ausdruck berechnen" + +#: mixlib/xmix_vm_handlers.c:85 +msgid "Convert a MIX word to its decimal value" +msgstr "MIX-Wort in seinen dezimalen Wert konvertieren" + +#: mixlib/xmix_vm_handlers.c:87 +msgid "Turn on/off instruction tracing" +msgstr "Instruktionsmitschnitt an/aus" + +#: mixlib/xmix_vm_handlers.c:89 +msgid "Print backtrace of executed instructions" +msgstr "Letzte ausgeführte Instruktionen anzeigen" + +#: mixlib/xmix_vm_handlers.c:91 +msgid "Turn on/off timing statistics" +msgstr "Zeitstatistik an/aus" + +#: mixlib/xmix_vm_handlers.c:93 +msgid "Print current time statistics" +msgstr "Aktuelle Zeitstatistik anzeigen" + +#: mixlib/xmix_vm_handlers.c:94 +msgid "Set devices directory" +msgstr "Device-Verzeichnis setzen" + +#: mixlib/xmix_vm_handlers.c:95 +msgid "Print current devices directory" +msgstr "Aktuelles Device-Verzeichnis anzeigen" + +#: mixlib/xmix_vm_handlers.c:96 +msgid "Turn on/off message logging" +msgstr "Message-Aufzeichnung an/aus" + +#: mixlib/xmix_vm_handlers.c:97 +msgid "Print the current program path" +msgstr "Aktuellen Programmpfad anzeigen" + +#: mixlib/xmix_vm_handlers.c:98 +msgid "Print the current program source path" +msgstr "Aktuellen Programmquellpfad anzeigen" + +#: mixlib/xmix_vm_handlers.c:100 +msgid "Print the current (or a given) program source line" +msgstr "Aktuelle (oder angegebene) Programmquellzeile anzeigen" + +#: mixlib/xmix_vm_handlers.c:167 +#, c-format +msgid "Elapsed time: %ld /Total program time: %ld (Total uptime: %ld)\n" +msgstr "" +"Vergangene Zeit: %ld /Gesamte Programmzeit: %ld (Gesamte Uptime: %ld)\n" + +#: mixlib/xmix_vm_handlers.c:194 +#, c-format +msgid "" +"%-15s%s.\n" +"%-15sUsage: %s\n" +msgstr "" +"%-15s%s.\n" +"%-15sAufruf: %s\n" + +#: mixlib/xmix_vm_handlers.c:198 +#, c-format +msgid "No commands match `%s'\n" +msgstr "Kein Kommando `%s'\n" + +#: mixlib/xmix_vm_handlers.c:204 +#, c-format +msgid "Possible commands are:\n" +msgstr "Mögliche Kommandos sind:\n" + +#: mixlib/xmix_vm_handlers.c:218 +msgid "Missing file name" +msgstr "Dateiname fehlt" + +#: mixlib/xmix_vm_handlers.c:225 +#, c-format +msgid "Cannot load %s: " +msgstr "Kann %s nicht laden: " + +#: mixlib/xmix_vm_handlers.c:227 +msgid "Wrong file format" +msgstr "Falsches Dateiformat" + +#: mixlib/xmix_vm_handlers.c:242 +#, c-format +msgid "Program loaded. Start address: %d" +msgstr "Programm geladen. Startadresse: %d" + +#: mixlib/xmix_vm_handlers.c:254 +msgid "Editor not specified (use sedit)" +msgstr "Editor nicht angegeben (verwende sedit)" + +#: mixlib/xmix_vm_handlers.c:260 mixlib/xmix_vm_handlers.c:285 +msgid "MIXAL source file path not found" +msgstr "MIXAL Quelldateipfad nicht gefunden" + +#: mixlib/xmix_vm_handlers.c:268 +msgid " ...done" +msgstr " ...fertig" + +#: mixlib/xmix_vm_handlers.c:279 +msgid "MIX assembler not specified (use sasm)" +msgstr "MIX-Assembler nicht angegeben (verwende sasm)" + +#: mixlib/xmix_vm_handlers.c:293 +msgid "Successful compilation" +msgstr "Kompilation erfolgreich" + +#: mixlib/xmix_vm_handlers.c:307 +msgid "Running ..." +msgstr "Arbeite ..." + +#: mixlib/xmix_vm_handlers.c:312 +msgid "... done" +msgstr "... fertig" + +#: mixlib/xmix_vm_handlers.c:320 +#, c-format +msgid "... stopped: breakpoint at line %ld (address %d)" +msgstr "... angehalten: Breakpoint bei Zeile %ld (Adresse %d)" + +#: mixlib/xmix_vm_handlers.c:323 +#, c-format +msgid "... stopped: breakpoint at address %d" +msgstr "... angehalten: Breakpoint bei Adresse %d" + +#: mixlib/xmix_vm_handlers.c:332 +#, c-format +msgid "... stopped: %s (line %ld, address %d)" +msgstr "... angehalten: %s (Zeile %ld, Adresse %d)" + +#: mixlib/xmix_vm_handlers.c:336 +#, c-format +msgid "... stopped: %s (address %d)" +msgstr "... angehalten: %s (Adresse %d)" + +#: mixlib/xmix_vm_handlers.c:342 mixlib/xmix_vm_handlers.c:389 +#, c-format +msgid "%s:" +msgstr "%s:" + +#: mixlib/xmix_vm_handlers.c:368 mixlib/xmix_vm_handlers.c:472 +#: mixlib/xmix_vm_handlers.c:536 mixlib/xmix_vm_handlers.c:605 +#: mixlib/xmix_vm_handlers.c:631 mixlib/xmix_vm_handlers.c:654 +#: mixlib/xmix_vm_handlers.c:695 mixlib/xmix_vm_handlers.c:740 +#: mixlib/xmix_vm_handlers.c:772 mixlib/xmix_vm_handlers.c:800 +#: mixlib/xmix_vm_handlers.c:834 +#, c-format +msgid "Invalid argument: %s" +msgstr "Ungültiges Argument: %s" + +#: mixlib/xmix_vm_handlers.c:383 +#, c-format +msgid "End of program reached at address %d" +msgstr "Ende des Programmes erreicht bei Adresse %d" + +#: mixlib/xmix_vm_handlers.c:412 +msgid "Symbol table not available" +msgstr "Symboltabelle fehlt" + +#: mixlib/xmix_vm_handlers.c:423 +#, c-format +msgid "%s: symbol not defined\n" +msgstr "%s: Symbol nicht definiert\n" + +#: mixlib/xmix_vm_handlers.c:464 +#, c-format +msgid "Invalid I index: %d" +msgstr "Ungültiger I-Index: %d" + +#: mixlib/xmix_vm_handlers.c:505 +msgid "Missing memory address" +msgstr "Speicheradresse fehlt" + +#: mixlib/xmix_vm_handlers.c:540 +#, c-format +msgid "Invalid range: %ld-%ld" +msgstr "Ungültiger Bereich: %ld-%ld" + +#: mixlib/xmix_vm_handlers.c:708 +msgid "Missing arguments" +msgstr "Argumente fehlen" + +#: mixlib/xmix_vm_handlers.c:725 +msgid "Wrong argument number" +msgstr "Falsche Argumenteanzahl" + +#: mixlib/xmix_vm_handlers.c:747 +#, c-format +msgid "Line number %ld too high" +msgstr "Zeilennummer %ld zu hoch" + +#: mixlib/xmix_vm_handlers.c:750 mixlib/xmix_vm_handlers.c:782 +#: mixlib/xmix_vm_handlers.c:810 +msgid "Could not set breakpoint: internal error" +msgstr "Kann Breakpoint nicht setzen: Interner Fehler" + +#: mixlib/xmix_vm_handlers.c:753 +msgid "Could not set breakpoint: no debug info available" +msgstr "Kann Breakpoint nicht setzen: Debuginformationen fehlen" + +#: mixlib/xmix_vm_handlers.c:758 +#, c-format +msgid "Breakpoint set at line %ld" +msgstr "Breakpoint bei Zeile %ld gesetzt" + +#: mixlib/xmix_vm_handlers.c:779 mixlib/xmix_vm_handlers.c:841 +#, c-format +msgid "Invalid address %ld" +msgstr "Ungültige Adresse %ld" + +#: mixlib/xmix_vm_handlers.c:786 +#, c-format +msgid "Breakpoint set at address %ld" +msgstr "Breakpoint bei Adresse %ld gesetzt" + +#: mixlib/xmix_vm_handlers.c:807 +#, c-format +msgid "No breakpoint set at line %ld" +msgstr "Kein Breakpoint bei Zeile %ld gesetzt" + +#: mixlib/xmix_vm_handlers.c:813 +msgid "No debug info available" +msgstr "Debuginformationen fehlen" + +#: mixlib/xmix_vm_handlers.c:817 +#, c-format +msgid "Breakpoint cleared at line %ld" +msgstr "Breakpoint bei Zeile %ld gelöscht" + +#: mixlib/xmix_vm_handlers.c:844 +msgid "Could not clear breakpoint: internal error" +msgstr "Kann Breakpoint nicht löschen: Interner Fehler" + +#: mixlib/xmix_vm_handlers.c:848 +#, c-format +msgid "Breakpoint cleared at address %ld" +msgstr "Breakpoint bei Adresse %ld gelöscht" + +#: mixlib/xmix_vm_handlers.c:860 mixlib/xmix_vm_handlers.c:1203 +#: mixlib/xmix_vm_handlers.c:1218 mixlib/xmix_vm_handlers.c:1238 +#: mixlib/xmix_vm_handlers.c:1253 +#, c-format +msgid "Unexpected argument: %s" +msgstr "Unerwartetes Argument: %s" + +#: mixlib/xmix_vm_handlers.c:872 mixlib/xmix_vm_handlers.c:904 +msgid "Missing expression" +msgstr "Ausdruck fehlt" + +#: mixlib/xmix_vm_handlers.c:893 +#, c-format +msgid "" +"\n" +"Evaluation error: %s\n" +msgstr "" +"\n" +"Ausführungsfehler: %s\n" + +#: mixlib/xmix_vm_handlers.c:920 +#, c-format +msgid "Incorrect byte specification: %s" +msgstr "Falsche Bytespezifikation: %s" + +#: mixlib/xmix_vm_handlers.c:935 +#, c-format +msgid "The expression %s does not fit in a word" +msgstr "Der Ausdruck %s paßt nicht in ein Wort" + +#: mixlib/xmix_vm_handlers.c:958 mixlib/xmix_vm_handlers.c:982 +#: mixlib/xmix_vm_handlers.c:1022 mixlib/xmix_vm_handlers.c:1045 +#: mixlib/xmix_vm_handlers.c:1055 +msgid "Missing argument" +msgstr "Argument fehlt" + +#: mixlib/xmix_vm_handlers.c:971 mixlib/xmix_vm_handlers.c:995 +#: mixlib/xmix_vm_handlers.c:1320 +msgid "Wrong argument: " +msgstr "Falsches Argument: " + +#: mixlib/xmix_vm_handlers.c:1011 +#, c-format +msgid "Edit command: %s\n" +msgstr "Editor: %s\n" + +#: mixlib/xmix_vm_handlers.c:1013 +#, c-format +msgid "Edit command not set (use sedit)\n" +msgstr "Editor nicht gesetzt (verwende sedit)\n" + +#: mixlib/xmix_vm_handlers.c:1034 +#, c-format +msgid "Compile command: %s\n" +msgstr "Kompiler: %s\n" + +#: mixlib/xmix_vm_handlers.c:1036 +#, c-format +msgid "Compile command not set (use sasm)\n" +msgstr "Kompiler nicht gesetzt (verwende sasm)\n" + +#: mixlib/xmix_vm_handlers.c:1064 +#, c-format +msgid "Device directory: %s\n" +msgstr "Device-Verzeichnis: %s\n" + +#: mixlib/xmix_vm_handlers.c:1111 +#, c-format +msgid "Conditional breakpoint on r%s change set" +msgstr "Conditional Breakpoint bei r%s-Änderung gesetzt" + +#: mixlib/xmix_vm_handlers.c:1116 mixlib/xmix_vm_handlers.c:1140 +#, c-format +msgid "Invalid argument %s" +msgstr "Ungültiges Argument %s" + +#: mixlib/xmix_vm_handlers.c:1131 +#, c-format +msgid "Conditional breakpoint on r%s change removed" +msgstr "Conditional Breakpoint bei r%s-Änderung gelöscht" + +#: mixlib/xmix_vm_handlers.c:1135 +#, c-format +msgid "No breakpoint set on r%s change" +msgstr "Keinen Breakpoint bei r%s-Änderung gesetzt" + +#: mixlib/xmix_vm_handlers.c:1152 mixlib/xmix_vm_handlers.c:1177 +#, c-format +msgid "Invalid memory address: %s" +msgstr "Ungültige Speicheradresse: %s" + +#: mixlib/xmix_vm_handlers.c:1165 +#, c-format +msgid "Conditional breakpoint on mem cell no. %d set" +msgstr "Conditional Breakpoint bei Speicherzelle %d gesetzt" + +#: mixlib/xmix_vm_handlers.c:1188 +#, c-format +msgid "Conditional breakpoint on mem cell no. %d removed" +msgstr "Conditional Breakpoint bei Speicherzelle %d gelöscht" + +#: mixlib/xmix_vm_handlers.c:1193 +#, c-format +msgid "No conditional breakpoint set at address %d" +msgstr "Keinen Conditional Breakpoint bei Adresse %d gesetzt" + +#: mixlib/xmix_vm_handlers.c:1209 +msgid "Conditional breakpoint on overflow toggled set" +msgstr "Conditional Breakpoint beim Overflow-Flag gesetzt" + +#: mixlib/xmix_vm_handlers.c:1226 +msgid "Conditional breakpoint on overflow toggled removed." +msgstr "Conditional Breakpoint beim Overflow-Flag gelöscht" + +#: mixlib/xmix_vm_handlers.c:1229 +msgid "No breakpoint set on overflow toggle" +msgstr "Keinen Breakpoint beim Overflow-Flag gesetzt" + +#: mixlib/xmix_vm_handlers.c:1244 +msgid "Conditional breakpoint on comparison flag changed set" +msgstr "Conditional Breakpoint beim Comparison-Flag gesetzt" + +#: mixlib/xmix_vm_handlers.c:1262 +msgid "Conditional breakpoint on comparison flag changed removed." +msgstr "Conditional Breakpoint beim Comparison-Flag gelöscht" + +#: mixlib/xmix_vm_handlers.c:1265 +msgid "No breakpoint set on comparison flag change" +msgstr "Keinen Breakpoint beim Comparison-Flag gesetzt" + +#: mixlib/xmix_vm_handlers.c:1328 +#, c-format +msgid "No program currently loaded" +msgstr "Zur Zeit kein Programm geladen" + +#: mixlib/xmix_vm_handlers.c:1337 +#, c-format +msgid "No program currently loaded\n" +msgstr "Zur Zeit kein Programm geladen\n" + +#: mixlib/xmix_vm_handlers.c:1352 +msgid "Invalid argument" +msgstr "Ungültiges Argument" + +#: mixlib/xmix_vm_handlers.c:1375 +msgid "Error loading or executing file" +msgstr "Fehler beim Laden oder Ausführen der Datei" + +#: mixlib/xmix_vm_handlers.c:1376 +msgid "Execution stopped: breakpoint encountered" +msgstr "Ausführung angehalten: auf Breakpoint gestoßen" + +#: mixlib/xmix_vm_handlers.c:1377 +msgid "Execution stopped: conditional breakpoint encountered" +msgstr "Ausführung angehalten: auf Conditional Breakpoint gestoßen" + +#: mixlib/xmix_vm_handlers.c:1378 +msgid "Program successfully terminated" +msgstr "Programm erfolgreich beendet" + +#: mixlib/xmix_vm_handlers.c:1379 +msgid "Execution stopped" +msgstr "Ausführung angehalten" + +#: mixlib/xmix_vm_handlers.c:1380 +msgid "Program successfully loaded" +msgstr "Programm erfolgreich geladen" + +#: mixlib/xmix_vm_handlers.c:1381 +msgid "No program loaded" +msgstr "Kein Programm geladen" + +#: mixgtk/mixgtk_device.c:543 +msgid "Devices folder" +msgstr "Device-Verzeichnis" + +#: mixgtk/mixgtk_gen_handlers.c:97 +msgid "Load MIX program..." +msgstr "MIX-Programm laden..." + +#: mixgtk/mixgtk_gen_handlers.c:110 +msgid "Edit MIXAL source file..." +msgstr "MIXAL-Quelldatei bearbeiten..." + +#: mixgtk/mixgtk_gen_handlers.c:124 +msgid "Compile MIXAL source file..." +msgstr "MIXAL-Quelldatei kompilieren..." + +#: mixgtk/mixgtk_mixal.c:340 mixgtk/mixgtk_mixal.c:341 +msgid "N/A" +msgstr "N/A" + +#: mixgtk/mixgtk_mixal.c:364 +msgid "Source not available" +msgstr "Quelle fehlt" + +#: mixgtk/mixgtk_mixvm.c:328 +msgid "Register A" +msgstr "Register A" + +#: mixgtk/mixgtk_mixvm.c:331 +msgid "Register X" +msgstr "Register X" + +#: mixgtk/mixgtk_mixvm.c:334 +msgid "Register J" +msgstr "Register J" + +#: mixgtk/mixgtk_mixvm.c:340 +#, c-format +msgid "Register I%d" +msgstr "Register I%d" + +#: mixgtk/mixgtk_mixvm.c:456 +#, c-format +msgid "Memory cell no. %d" +msgstr "Speicherzelle %d" + +#: mixgtk/gmixvm.c:97 +msgid "gmixvm, GTK MIX virtual machine" +msgstr "gmixvm, GTK MIX virtuelle Maschine" + +#: mixgtk/mixgtk.c:45 +msgid "Unable to load gmixvm configuration" +msgstr "Kann gmixvm-Konfiguration nicht laden" + +#: mixgtk/mixgtk.c:50 +msgid "Unable to initialise application: missing glade file" +msgstr "Kann Applikation nicht initialisieren: Glade-Datei fehlt" + +#: mixgtk/mixgtk.c:56 +msgid "Unable to initialise application\n" +msgstr "Kann Applikation nicht initialisieren\n" + +#: mixgtk/mixgtk.glade:7 +msgid "gmixvm" +msgstr "gmixvm" + +#: mixgtk/mixgtk.glade:36 +msgid "_File" +msgstr "Datei" + +#: mixgtk/mixgtk.glade:45 +msgid "Load a MIX file" +msgstr "Lade eine MIX-Datei" + +#: mixgtk/mixgtk.glade:46 +msgid "_Load..." +msgstr "_Laden..." + +#: mixgtk/mixgtk.glade:69 +msgid "_Edit..." +msgstr "Bearbeiten..." + +#: mixgtk/mixgtk.glade:92 +msgid "_Compile..." +msgstr "Kompilieren..." + +#: mixgtk/mixgtk.glade:120 +msgid "Exit application" +msgstr "Applikation beenden" + +#: mixgtk/mixgtk.glade:121 +msgid "E_xit" +msgstr "Beenden" + +#: mixgtk/mixgtk.glade:147 +msgid "De_bug" +msgstr "De_bug" + +#: mixgtk/mixgtk.glade:156 +msgid "Run program" +msgstr "Starte Programm" + +#: mixgtk/mixgtk.glade:157 +msgid "_Run" +msgstr "Starte" + +#: mixgtk/mixgtk.glade:179 +msgid "Execute next instruction" +msgstr "Führe nächste Instruktion aus" + +#: mixgtk/mixgtk.glade:180 +msgid "_Next" +msgstr "Weiter" + +#: mixgtk/mixgtk.glade:202 +msgid "Clear all set breakpoints" +msgstr "Alle gesetzten Breakpoints löschen" + +#: mixgtk/mixgtk.glade:203 +msgid "_Clear breakpoints" +msgstr "Breakpoints löschen" + +#: mixgtk/mixgtk.glade:225 +msgid "Show the symbol table" +msgstr "Zeige Symboltabelle" + +#: mixgtk/mixgtk.glade:226 +msgid "_Symbols..." +msgstr "_Symbole..." + +#: mixgtk/mixgtk.glade:252 +msgid "Vie_w" +msgstr "Ansicht" + +#: mixgtk/mixgtk.glade:261 +msgid "_Toolbars" +msgstr "_Toolbar" + +#: mixgtk/mixgtk.glade:270 +msgid "_Detached windows" +msgstr "_Detached Fenster" + +#: mixgtk/mixgtk.glade:291 mixgtk/mixgtk.glade:356 +msgid "_Virtual machine" +msgstr "_Virtuelle Maschine" + +#: mixgtk/mixgtk.glade:300 mixgtk/mixgtk.glade:365 +msgid "_Source" +msgstr "Quelle" + +#: mixgtk/mixgtk.glade:309 mixgtk/mixgtk.glade:392 +msgid "_Devices" +msgstr "_Devices" + +#: mixgtk/mixgtk.glade:326 +msgid "S_ettings" +msgstr "W_erte" + +#: mixgtk/mixgtk.glade:335 +msgid "Change _font" +msgstr "Font ändern" + +#: mixgtk/mixgtk.glade:374 +msgid "Command _prompt" +msgstr "Kommando_prompt" + +#: mixgtk/mixgtk.glade:383 +msgid "Command l_og" +msgstr "K_ommandoaufzeichnung" + +#: mixgtk/mixgtk.glade:401 +msgid "Symbol _list" +msgstr "Symbol_liste" + +#: mixgtk/mixgtk.glade:416 +msgid "Change all fonts at once" +msgstr "Alle Fonts auf einmal ändern" + +#: mixgtk/mixgtk.glade:417 +msgid "_All" +msgstr "_Alles" + +#: mixgtk/mixgtk.glade:430 +msgid "Change format of binary devices output" +msgstr "Format für binäre Device-Ausgabe ändern" + +#: mixgtk/mixgtk.glade:431 +msgid "_Device output..." +msgstr "_Device-Ausgabe..." + +#: mixgtk/mixgtk.glade:452 +msgid "De_vices dir..." +msgstr "De_vices-Verzeichnis..." + +#: mixgtk/mixgtk.glade:473 +msgid "E_xternal programs..." +msgstr "E_xterne Programm..." + +#: mixgtk/mixgtk.glade:500 +msgid "Save current settings" +msgstr "Aktuellen Werte speichern" + +#: mixgtk/mixgtk.glade:501 +msgid "_Save" +msgstr "_Speichern" + +#: mixgtk/mixgtk.glade:522 +msgid "Toogle save settings on exit" +msgstr "Speichern beim Beenden an/aus" + +#: mixgtk/mixgtk.glade:523 +msgid "Save on _exit" +msgstr "Speichern beim B_eenden" + +#: mixgtk/mixgtk.glade:537 +msgid "_Help" +msgstr "_Hilfe" + +#: mixgtk/mixgtk.glade:546 +msgid "_About..." +msgstr "Über..." + +#: mixgtk/mixgtk.glade:593 +msgid "Load MIX program" +msgstr "Lade MIX-Programm" + +#: mixgtk/mixgtk.glade:594 +msgid "Open" +msgstr "Öffnen" + +#: mixgtk/mixgtk.glade:611 +msgid "Compile MIXAL source" +msgstr "MIXAL-Quelle kompilieren" + +#: mixgtk/mixgtk.glade:612 +msgid "Compile" +msgstr "Kompilieren" + +#: mixgtk/mixgtk.glade:629 +msgid "Edit MIXAL source" +msgstr "MIXAL-Quelle bearbeiten" + +#: mixgtk/mixgtk.glade:630 +msgid "Edit" +msgstr "Bearbeiten" + +#: mixgtk/mixgtk.glade:647 mixgtk/mixgtk.glade:648 mixgtk/mixgtk.glade:2147 +#: mixgtk/mixgtk.glade:2148 +msgid "Run" +msgstr "Start" + +#: mixgtk/mixgtk.glade:665 mixgtk/mixgtk.glade:666 mixgtk/mixgtk.glade:2165 +msgid "Next" +msgstr "Weiter" + +#: mixgtk/mixgtk.glade:683 mixgtk/mixgtk.glade:2183 +msgid "Clear breakpoints" +msgstr "Breakpoints löschen" + +#: mixgtk/mixgtk.glade:684 mixgtk/mixgtk.glade:2184 +msgid "Clear" +msgstr "Löschen" + +#: mixgtk/mixgtk.glade:701 mixgtk/mixgtk.glade:1969 mixgtk/mixgtk.glade:2201 +msgid "Symbol table" +msgstr "Symboltabelle" + +#: mixgtk/mixgtk.glade:702 mixgtk/mixgtk.glade:2202 +msgid "Symbols" +msgstr "Symbole" + +#: mixgtk/mixgtk.glade:732 mixgtk/mixgtk.glade:2362 +msgid "Device directory" +msgstr "Device-Verzeichnis" + +#: mixgtk/mixgtk.glade:733 +msgid "Devdir" +msgstr "Dev-Verz" + +#: mixgtk/mixgtk.glade:750 mixgtk/mixgtk.glade:2380 +msgid "Output format" +msgstr "Ausgabeformat" + +#: mixgtk/mixgtk.glade:751 mixgtk/mixgtk.glade:1683 +msgid "Format" +msgstr "Format" + +#: mixgtk/mixgtk.glade:768 mixgtk/mixgtk.glade:1785 +msgid "External programs" +msgstr "Externe Programme" + +#: mixgtk/mixgtk.glade:769 +msgid "Programs" +msgstr "Programme" + +#: mixgtk/mixgtk.glade:799 +msgid "Detach window" +msgstr "Detach-Fenster" + +#: mixgtk/mixgtk.glade:800 +msgid "Detach" +msgstr "Detach" + +#: mixgtk/mixgtk.glade:817 +msgid "Attach all windows" +msgstr "Alle Fenster zuordnen" + +#: mixgtk/mixgtk.glade:906 +msgid "Enter MIXVM command here" +msgstr "MIXVM-Kommando hier eingeben" + +#: mixgtk/mixgtk.glade:914 mixgtk/mixgtk.glade:1050 mixgtk/mixgtk.glade:1073 +#: mixgtk/mixgtk.glade:1096 mixgtk/mixgtk.glade:1119 mixgtk/mixgtk.glade:1142 +#: mixgtk/mixgtk.glade:1165 mixgtk/mixgtk.glade:1188 mixgtk/mixgtk.glade:1475 +#: mixgtk/mixgtk.glade:1867 mixgtk/mixgtk.glade:1920 mixgtk/mixgtk.glade:2585 +#: mixgtk/mixgtk.glade:2843 mixgtk/mixgtk.glade:2869 mixgtk/mixgtk.glade:2895 +#: mixgtk/mixgtk.glade:3077 mixgtk/mixgtk.glade:3103 mixgtk/mixgtk.glade:3129 +#: mixgtk/mixgtk.glade:3155 mixgtk/mixgtk.glade:3181 mixgtk/mixgtk.glade:3213 +#: mixgtk/mixgtk.glade:3452 mixgtk/mixgtk.glade:3892 +msgid "*" +msgstr "*" + +#: mixgtk/mixgtk.glade:955 mixgtk/mixgtk.glade:1248 +msgid "Enter value" +msgstr "Wert eingeben" + +#: mixgtk/mixgtk.glade:1048 mixgtk/mixgtk.glade:1071 mixgtk/mixgtk.glade:1094 +#: mixgtk/mixgtk.glade:1117 mixgtk/mixgtk.glade:1140 mixgtk/mixgtk.glade:1163 +#: mixgtk/mixgtk.glade:3450 +msgid "0" +msgstr "0" + +#: mixgtk/mixgtk.glade:1186 +msgid "+" +msgstr "+" + +#: mixgtk/mixgtk.glade:1204 mixgtk/mixgtk.glade:1757 +msgid "Decimal" +msgstr "Dezimal" + +#: mixgtk/mixgtk.glade:1226 +msgid "Bytes" +msgstr "Bytes" + +#: mixgtk/mixgtk.glade:1276 +msgid "MDK" +msgstr "MDK" + +#: mixgtk/mixgtk.glade:1306 +msgid "GNU MIX Development Kit" +msgstr "GNU MIX Development Kit" + +#: mixgtk/mixgtk.glade:1328 +msgid "label223" +msgstr "Label 223" + +#: mixgtk/mixgtk.glade:1350 +msgid "" +" Copyright (C) 2001, 2002, 2003 , 2004\n" +"Free Software Foundation, Inc.\n" +"\n" +"Please, send bug reports to\n" +"bug-mdk@gnu.org" +msgstr "" +" Copyright (C) 2001, 2002, 2003, 2004\n" +"Free Software Foundation, Inc.\n" +"\n" +"Bitte senden Sie Bug-Reports an\n" +"bug-mdk@gnu.org" + +#: mixgtk/mixgtk.glade:1375 +msgid "Go to memory cell" +msgstr "Gehe zur Speicherzelle" + +#: mixgtk/mixgtk.glade:1447 +msgid "Go to address:" +msgstr "Gehe zu Adresse:" + +#: mixgtk/mixgtk.glade:1497 +msgid "Select Font" +msgstr "Wähle Font" + +#: mixgtk/mixgtk.glade:1546 +msgid "abcdefghijk ABCDEFGHIJK" +msgstr "abcdefghijk ABCDEFGHIJK" + +#: mixgtk/mixgtk.glade:1557 +msgid "Device output format" +msgstr "Device-Ausgabeformat" + +#: mixgtk/mixgtk.glade:1642 +msgid "Set all devices to current format" +msgstr "Alle Devices auf das aktuelle Format setzen" + +#: mixgtk/mixgtk.glade:1644 +msgid "S_et all" +msgstr "Alles S_etzen" + +#: mixgtk/mixgtk.glade:1661 +msgid "Device" +msgstr "Device" + +#: mixgtk/mixgtk.glade:1705 +msgid "" +"tape0\n" +"tape1\n" +"tape2\n" +"tape3\n" +"tape4\n" +"tape5\n" +"tape6\n" +"tape7\n" +"disk0\n" +"disk1\n" +"disk2\n" +"disk3\n" +"disk4\n" +"disk5\n" +"disk6\n" +"disk7" +msgstr "" +"tape0\n" +"tape1\n" +"tape2\n" +"tape3\n" +"tape4\n" +"tape5\n" +"tape6\n" +"tape7\n" +"disk0\n" +"disk1\n" +"disk2\n" +"disk3\n" +"disk4\n" +"disk5\n" +"disk6\n" +"disk7" + +#: mixgtk/mixgtk.glade:1734 +msgid "Show output as MIX words" +msgstr "Zeige Ausgabe als MIX-Wörter" + +#: mixgtk/mixgtk.glade:1736 +msgid "Word" +msgstr "Wort" + +#: mixgtk/mixgtk.glade:1755 +msgid "Show output as decimal numbers" +msgstr "Zeige Ausgabe als dezimale Zahlen" + +#: mixgtk/mixgtk.glade:1865 +msgid "xterm -e vi %s" +msgstr "xterm -e vi %s" + +#: mixgtk/mixgtk.glade:1881 +msgid "Editor command (e.g xterm -e vi %s)" +msgstr "Editor-Befehl (z.B. xterm -e vi %s)" + +#: mixgtk/mixgtk.glade:1918 +msgid "mixasm %s" +msgstr "mixasm %s" + +#: mixgtk/mixgtk.glade:1934 +msgid "MIX sssembler command (e.g. mixasm %s)" +msgstr "MIX-Assembler-Befehl (z.B. mixasm %s)" + +#: mixgtk/mixgtk.glade:2045 +msgid "_Close" +msgstr "Schließen" + +#: mixgtk/mixgtk.glade:2107 +msgid "MIXAL source" +msgstr "MIXAL Quelle" + +#: mixgtk/mixgtk.glade:2166 +msgid "Step" +msgstr "Schritt" + +#: mixgtk/mixgtk.glade:2232 +msgid "Source code font" +msgstr "Quellcodefont" + +#: mixgtk/mixgtk.glade:2233 mixgtk/mixgtk.glade:2412 mixgtk/mixgtk.glade:2662 +msgid "Font" +msgstr "Font" + +#: mixgtk/mixgtk.glade:2263 +msgid "Attach window" +msgstr "Attach-Fenster" + +#: mixgtk/mixgtk.glade:2319 +msgid "Devices" +msgstr "Devices" + +#: mixgtk/mixgtk.glade:2363 mixgtk/mixgtk.glade:2558 +msgid "Directory" +msgstr "Verzeichnis" + +#: mixgtk/mixgtk.glade:2381 +msgid "Output" +msgstr "Ausgabe" + +#: mixgtk/mixgtk.glade:2411 +msgid "Output font" +msgstr "Ausgabefont" + +#: mixgtk/mixgtk.glade:2485 +msgid "Devices directory" +msgstr "Device-Verzeichnis" + +#: mixgtk/mixgtk.glade:2623 +msgid "Virtual machine" +msgstr "Virtuelle Maschine" + +#: mixgtk/mixgtk.glade:2758 +msgid "A" +msgstr "A" + +#: mixgtk/mixgtk.glade:2784 +msgid "I1" +msgstr "I1" + +#: mixgtk/mixgtk.glade:2810 +msgid "I2" +msgstr "I2" + +#: mixgtk/mixgtk.glade:2915 +msgid "X" +msgstr "X" + +#: mixgtk/mixgtk.glade:2941 +msgid "I3" +msgstr "I3" + +#: mixgtk/mixgtk.glade:2967 +msgid "I4" +msgstr "I4" + +#: mixgtk/mixgtk.glade:2993 +msgid "I5" +msgstr "I5" + +#: mixgtk/mixgtk.glade:3019 +msgid "I6" +msgstr "I6" + +#: mixgtk/mixgtk.glade:3045 +msgid "J" +msgstr "J" + +#: mixgtk/mixgtk.glade:3244 +msgid "Registers " +msgstr "Register " + +#: mixgtk/mixgtk.glade:3294 +msgid "Greater" +msgstr "Größer" + +#: mixgtk/mixgtk.glade:3296 +msgid "G" +msgstr "G" + +#: mixgtk/mixgtk.glade:3318 +msgid "Equal" +msgstr "Gleich" + +#: mixgtk/mixgtk.glade:3320 +msgid "E" +msgstr "E" + +#: mixgtk/mixgtk.glade:3343 +msgid "Lesser" +msgstr "Kleiner" + +#: mixgtk/mixgtk.glade:3345 +msgid "L" +msgstr "L" + +#: mixgtk/mixgtk.glade:3378 +msgid "Overflow" +msgstr "Overflow" + +#: mixgtk/mixgtk.glade:3399 +msgid "Flags " +msgstr "Flags " + +#: mixgtk/mixgtk.glade:3466 +msgid "View loc address" +msgstr "Zeige Positionsadresse" + +#: mixgtk/mixgtk.glade:3496 +msgid "Location " +msgstr "Position " + +#: mixgtk/mixgtk.glade:3547 +msgid "Uptime:" +msgstr "Uptime:" + +#: mixgtk/mixgtk.glade:3570 +msgid "00000000" +msgstr "00000000" + +#: mixgtk/mixgtk.glade:3593 +msgid "Elapsed:" +msgstr "Verbraucht" + +#: mixgtk/mixgtk.glade:3616 mixgtk/mixgtk.glade:3662 +msgid "000000" +msgstr "000000" + +#: mixgtk/mixgtk.glade:3639 +msgid "Program:" +msgstr "Programm:" + +#: mixgtk/mixgtk.glade:3685 +msgid "Times " +msgstr "Times " + +#: mixgtk/mixgtk.glade:3750 +msgid "Memory " +msgstr "Speicher " + +#: mixgtk/mixgtk.glade:3779 +msgid "MIX Virtual Machine " +msgstr "MIX virtuelle Maschine" + +#: mixgtk/mixgtk.glade:3807 +msgid "MIX Console input" +msgstr "MIX-Konsoleeingabe" + +#: mixgtk/mixgtk.glade:3865 +msgid "Enter up to 70 characters" +msgstr "Bis zu 70 Zeichen eingeben" + +#: mixguile/mixguile.c:74 +#, c-format +msgid "mixguile bootstrap file %s not found\n" +msgstr "Mixguile-Bootstrap-Datei %s nicht gefunden\n" + +#: mixguile/mixguile_cmd_dispatcher.c:52 +msgid "Eval Scheme command using Guile" +msgstr "Führe Scheme-Kommando aus mit Guile" + +#: mixguile/mixguile_cmd_dispatcher.c:53 +msgid "Eval Scheme file using Guile" +msgstr "Führe Scheme-Datei aus mit Guile" diff --git a/samples/Makefile.am b/samples/Makefile.am new file mode 100644 index 0000000..5b1ceff --- /dev/null +++ b/samples/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to produce Makefile.in + +# Copyright (C) 2000, 2001, 2004 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. + +# $Id: Makefile.am,v 1.3 2004/06/09 13:16:42 jao Exp $ + +EXTRA_DIST = primes.result hello.mixal primes.mixal echo.mixal\ + permutations.mixal permutations.cardrd \ No newline at end of file diff --git a/samples/echo.mixal b/samples/echo.mixal new file mode 100644 index 0000000..9b87adf --- /dev/null +++ b/samples/echo.mixal @@ -0,0 +1,10 @@ +* read from the console +TERM EQU 19 +MSG EQU 500 +PRINT EQU 20 + ORIG 1000 +START IN MSG(TERM) +* JBUS *(TERM) + OUT MSG(TERM) + HLT + END START 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/m.mixal b/samples/m.mixal new file mode 100644 index 0000000..ae69b42 --- /dev/null +++ b/samples/m.mixal @@ -0,0 +1,25 @@ +X EQU 1000 + ORIG 3000 +MAXIMUM STJ EXIT +INIT ENT3 0,1 + JMP CHANGEM +LOOP CMPA X,3 + JGE *+3 +CHANGEM ENT2 0,3 + LDA X,3 + DEC3 1 + J3P LOOP +EXIT JMP * +START IN X+1(0) + JBUS *(0) + ENT1 100 +1H JMP MAXIMUM + LDX X,1 + STA X,1 + STX X,2 + DEC1 1 + J1P 1B + OUT X+1(1) + HLT + END START + diff --git a/samples/permutations.cardrd b/samples/permutations.cardrd new file mode 100644 index 0000000..639c1fe --- /dev/null +++ b/samples/permutations.cardrd @@ -0,0 +1,3 @@ + ( A C F G ) ( B C D ) ( A E D ) + ( F A D E ) ( B g F a E ) = + diff --git a/samples/permutations.mixal b/samples/permutations.mixal new file mode 100644 index 0000000..2c26df5 --- /dev/null +++ b/samples/permutations.mixal @@ -0,0 +1,89 @@ +* multiply permutations in cycle form (taopc p. 168) +* +MAXWDS EQU 1200 +PERM ORIG *+MAXWDS +ANS ORIG *+MAXWDS +OUTBUF ORIG *+24 +CARDS EQU 16 +PRINTER EQU 18 +BEGIN IN PERM(CARDS) + ENT2 0 + LDA EQUALS +1H JBUS *(CARDS) + CMPA PERM+15,2 + JE *+2 + IN PERM+16,2(CARDS) + ENT1 OUTBUF + JBUS *(PRINTER) + MOVE PERM,2(16) + OUT OUTBUF(PRINTER) + JE 1F + INC2 16 + CMP2 =MAXWDS-16= + JLE 1B + HLT 666 +1H INC2 15 + ST2 SIZE + ENT3 0 +2H LDAN PERM,3 + CMPA LPREN(1:5) + JNE 1F + STA PERM,3 + INC3 1 + LDXN PERM,3 + JXZ *-2 +1H CMPA RPREN(1:5) + JNE *+2 + STX PERM,3 + INC3 1 + CMP3 SIZE + JL 2B + LDA LPREN + ENT1 ANS +OPEN ENT3 0 +1H LDXN PERM,3 + JXN GO + INC3 1 + CMP3 SIZE + JL 1B +* +DONE CMP1 =ANS= + JNE *+2 + MOVE LPREN(2) + MOVE =0= + MOVE -1,1(22) + ENT3 0 + OUT ANS,3(PRINTER) + INC3 24 + LDX ANS,3 + JXNZ *-3 + HLT +* +LPREN ALF " (" +RPREN ALF ") " +EQUALS ALF " =" +* +GO MOVE LPREN + MOVE PERM,3 + STX START +SUCC STX PERM,3 + INC3 1 + LDXN PERM,3(1:5) + JXN 1F + JMP *-3 +5H STX 0,1 + INC1 1 + ENT3 0 +4H CMPX PERM,3(1:5) + JE SUCC +1H INC3 1 + CMP3 SIZE + JL 4B + CMPX START(1:5) + JNE 5B +CLOSE MOVE RPREN + CMPA -3,1 + JNE OPEN + INC1 -3 + JMP OPEN + END BEGIN diff --git a/samples/primes.mixal b/samples/primes.mixal new file mode 100644 index 0000000..365db32 --- /dev/null +++ b/samples/primes.mixal @@ -0,0 +1,53 @@ +* table of primes (taopc p. 148) +* +L EQU 500 +OUTDEV EQU 18 the printer +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 + 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/tests/bt.mixal b/samples/tests/bt.mixal new file mode 100644 index 0000000..00306ae --- /dev/null +++ b/samples/tests/bt.mixal @@ -0,0 +1,6 @@ + ORIG 0 +BEG JMP *+1 + JMP *+1 +FOO JMP BAR +BAR HLT + END BEG diff --git a/samples/tests/cbp.mixal b/samples/tests/cbp.mixal new file mode 100644 index 0000000..8c7b394 --- /dev/null +++ b/samples/tests/cbp.mixal @@ -0,0 +1,14 @@ +* testing conditional breakpoints + ORIG 2000 +START ENTA 100 + STA 1000 + ENTX 200 + STX 1001 + CMPA 1001 * cmp flag changed + CMPX 1000 * cmp flag changed + DIV 1002 * over toggle + HLT + END START + + + diff --git a/samples/tests/ldan.mixal b/samples/tests/ldan.mixal new file mode 100644 index 0000000..d15c6a3 --- /dev/null +++ b/samples/tests/ldan.mixal @@ -0,0 +1,5 @@ +VAR ORIG *+1 +BEGIN LDAN VAR(1:5) + LDXN VAR(1:5) + HLT + END BEGIN diff --git a/samples/tests/lockonw.mixal b/samples/tests/lockonw.mixal new file mode 100644 index 0000000..3ddad65 --- /dev/null +++ b/samples/tests/lockonw.mixal @@ -0,0 +1,3 @@ +* test for bug #5654 +START CMPA =0=(1:4) + END START diff --git a/samples/tests/negwrite.mixal b/samples/tests/negwrite.mixal new file mode 100644 index 0000000..dfed659 --- /dev/null +++ b/samples/tests/negwrite.mixal @@ -0,0 +1,4 @@ +* test for bug #5649: invalid address in OUT +START OUT -1(18) + HLT + END START diff --git a/samples/tests/stress0.mixal b/samples/tests/stress0.mixal new file mode 100644 index 0000000..d87b743 --- /dev/null +++ b/samples/tests/stress0.mixal @@ -0,0 +1,8 @@ + ORIG 1999 +ST NOP +* SYM EQU SYM+1 +SYM2 CON SYM2+1 +SYM3 ORIG SYM3+2 +SYM4 ENTA SYM4+1 + HLT +SYM5 END SYM5+1 diff --git a/samples/tests/stress1.mixal b/samples/tests/stress1.mixal new file mode 100644 index 0000000..f9bc8c9 --- /dev/null +++ b/samples/tests/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/tests/stress2.mixal b/samples/tests/stress2.mixal new file mode 100644 index 0000000..0c4d7d6 --- /dev/null +++ b/samples/tests/stress2.mixal @@ -0,0 +1,7 @@ + ORIG 1999 +ST NOP +SYM EQU SYM+1 +SYM2 CON SYM2+1 +SYM3 ORIG SYM3+2 + HLT +SYM4 END SYM4+1 diff --git a/samples/tests/stress4.mixal b/samples/tests/stress4.mixal new file mode 100644 index 0000000..7bcdd2a --- /dev/null +++ b/samples/tests/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 diff --git a/samples/tests/stress5.mixal b/samples/tests/stress5.mixal new file mode 100644 index 0000000..fce18cb --- /dev/null +++ b/samples/tests/stress5.mixal @@ -0,0 +1,17 @@ +* checking output to binary device +OUTDEV EQU 1 device for output +FROM EQU 1000 +TO EQU 1099 +INITVAL EQU 1 +STEP EQU 10 + ORIG 2000 +START ENTA INITVAL + ST1 0 +LOOP STA FROM,1 + INC1 1 + INCA STEP + CMP1 =TO-FROM+1= + JNE LOOP + OUT FROM(OUTDEV) + HLT + END START diff --git a/samples/tests/stress6.mixal b/samples/tests/stress6.mixal new file mode 100644 index 0000000..a80b7c9 --- /dev/null +++ b/samples/tests/stress6.mixal @@ -0,0 +1,9 @@ +* checking input from binary device +INDEV EQU 1 device for input +OUTDEV EQU 2 device for output +MEM EQU 1000 + ORIG 2000 +START IN MEM(INDEV) + OUT MEM(OUTDEV) + HLT + END START diff --git a/updatelog b/updatelog new file mode 100755 index 0000000..4ac1d1c --- /dev/null +++ b/updatelog @@ -0,0 +1 @@ +cvs2cl --fsf -S -P -- cgit v1.2.3