diff options
179 files changed, 38640 insertions, 0 deletions
@@ -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. @@ -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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 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. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..2991320 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,431 @@ +2005-09-20 Jose Antonio Ortega Ruiz <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <pieter.pareit@scarlet.be> + + * 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 <gray@gnu.org> + + * 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) + (<ADDRESS>): Accept w-expressions in literals (between = =). + +2004-08-05 Jose Antonio Ortega Ruiz <jao@gnu.org> + + * 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 <jao@gnu.org> + + * doc: documentation cleanup. + +2004-08-02 Jose Antonio Ortega Ruiz <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * mixlib/mix_parser.c: do not store bogus line number for added + CON instructions. + +2004-06-12 Jose Antonio Ortega Ruiz <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * configure.in: check for guile headers. + +2003-06-09 Jose A Ortega Ruiz <jao@gnu.org> + + * mdk (Module): version 1.0.1 tagged (v1r0_1) and released. + +2003-06-09 Jose A Ortega Ruiz <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * mixguile/xmixguile_cmd_dispatcher.c: Missing standard header for + strlen #included. + +2003-02-13 Pieter E J Pareit <pieter.pareit@skynet.be> + + * 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 <pieter.pareit@skynet.be> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * 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 <jao@gnu.org> + + * Makefile.am, aclocal.m4, configure.in, mixlib/gettext.h, + mixlib/mix.h: corrections to gettext infrastructure. + +2002-12-08 Jose A Ortega Ruiz <jao@gnu.org> + + * autogen.sh: use autopoint instead of gettextize. + +2002-10-19 Jose A Ortega Ruiz <jao@gnu.org> + + * THANKS: Vasilij removed, as he requested. + +2002-04-11 Jose A Ortega Ruiz <jao@gnu.org> + + * 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 <jao@gnu.org> + + * po/POTFILES.in: file list updated. + +2002-04-10 Jose A Ortega Ruiz <jao@gnu.org> + + * mixgtk/: mixgtk_mixal.c, mixgtk_mixvm.c: sprintf -> g_snprintf. + +2002-04-10 Jose A Ortega Ruiz <jao@gnu.org> + + * mixlib/xmix_vm_handlers.c: bug fix in 'load' command. + +2002-04-10 Jose A Ortega Ruiz <jao@gnu.org> + + * 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) + @@ -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: + + * <ftp://ftp.gnu.org/pub/gnu/mdk> (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 @@ -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 + <anp@cantv.net>. + +** 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 $ @@ -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 @@ -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 (<rms@gnu.org>) suggested various improvements to + the documentation and has always kept an eye on every MDK release. + + * Philip Ellis King (<pking@pdq.net>) 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 (<pieter.pareit@skynet.be>) is the author of + the Emacs MIXAL mode, and has also contributed many bug fixes. + + * Michael Scholz (<scholz-micha@gmx.de>) is the author of the + German translation of MDK's user interface. + + * Sergey Poznyakoff(<gray@gnu.org>) provided patches to + mixlib/mix_scanner.l improving MIXAL compliance. + + * Francesc Xavier Noria (<fxn@retemail.es>) kindly and thoroughly + reviewed the MDK documentation, providing insightful advice. + + * Agustin Navarro (<anp@cantv.net>), Ying-Chieh Liao + (<ijliao@csie.nctu.edu.tw>), Adrian Bunk (<bunk@fs.tum.de>), + Baruch Even (<baruch@debian.org>) and Ronald Cole + (<ronald@forte-intl.com>) created and/or maintain packages of MDK + for different operating systems. + + * Jason Uhlenkott, Andrew Hood (<ajhood@fl.net.au>), Radu Butnaru + (<rbb@email.ro>), Aleix Conchillo (<aleix@member.fsf.org>), + Ruslan Batdalov (<linnando@tolkien.ru>), WeiZheng + (<pro_zw@lol365.com>) and Sascha Wilde reported (sometimes with + fixes) several bugs in MDK. + + * Nelson H. F. Beebe (<beebe@math.utah.edu>, + 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 (<nathusiu@gmx.net>), Stephen Ramsay + (<sjr3a@virginia.edu>) and Johan Swanljung (<johanswa@yahoo.com>) + tested MDK on different platforms. + + * Eli Bendersky (<spur4444@yahoo.com>), Milan Bella + (<milanbella@hotmail.com>) 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 $ + @@ -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 <title> 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> +<meta http-equiv="content-type" content='text/html; charset=utf-8' /> +<link rel="stylesheet" type="text/css" href="/gnu.css" /> +<link rev="made" href="webmasters@gnu.org" /> +</head> + +<!-- This document is in XML, and xhtml 1.0 --> +<!-- Please make sure to properly nest your tags --> +<!-- and ensure that your final document validates --> +<!-- consistent with W3C xhtml 1.0 and CSS standards --> +<!-- See validator.w3.org --> + +<body> + +<h3>%%TITLE%%</h3> + +<address>Free Software Foundation</address> +<address>last updated %%DATE%%</address> +<p> +<a href="/graphics/gnu-head.jpg"> + <img src="/graphics/gnu-head-sm.jpg" + alt=" [image of the head of a GNU] " + width="129" height="122" /> +</a> +<a href="/philosophy/gif.html">(no gifs due to patent problems)</a> +</p> +<hr /> + +<p>This manual (%%PACKAGE%%) is available in the following formats:</p> + +<ul> + <li><a href="%%PACKAGE%%.html">HTML + (%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li> + <li><a href="html_node/index.html">HTML</a> - with one web page per + node.</li> + <li><a href="%%PACKAGE%%.html.gz">HTML compressed + (%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on + one web page.</li> + <li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed + (%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> - + with one web page per node.</li> + <li><a href="%%PACKAGE%%.info.tar.gz">Info document + (%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li> + <li><a href="%%PACKAGE%%.txt">ASCII text + (%%ASCII_SIZE%%K characters)</a>.</li> + <li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed + (%%ASCII_GZ_SIZE%%K gzipped characters)</a>.</li> + <li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file + (%%DVI_GZ_SIZE%%K characters gzipped)</a>.</li> + <li><a href="%%PACKAGE%%.ps.gz">PostScript file + (%%PS_GZ_SIZE%%K characters gzipped)</a>.</li> + <li><a href="%%PACKAGE%%.pdf">PDF file + (%%PDF_SIZE%%K characters)</a>.</li> + <li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source + (%%TEXI_TGZ_SIZE%%K characters gzipped tar file)</a></li> +</ul> + +<p>(This page generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%% +script</a>.)</p> + +<div class="copyright"> +<p> +Return to the <a href="/home.html">GNU Project home page</a>. +</p> + +<p> +Please send FSF & GNU inquiries to +<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>. +There are also <a href="/home.html#ContactInfo">other ways to contact</a> +the FSF. +<br /> +Please send broken links and other corrections (or suggestions) to +<a href="mailto:webmasters@gnu.org"><em>webmasters@gnu.org</em></a>. +</p> + +<p> +Copyright (C) 2004 Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02111, USA +<br /> +Verbatim copying and distribution of this entire article is +permitted in any medium, provided this notice is preserved. +</p> + +<p> +Updated: +<!-- timestamp start --> +$Date: 2005/09/20 20:18:58 $ $Author: jao $ +<!-- timestamp end --> +</p> +</div> + +</body> +</html> 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 Binary files differnew file mode 100644 index 0000000..009fa43 --- /dev/null +++ b/doc/img/ss_devdir.jpg diff --git a/doc/img/ss_devform.jpg b/doc/img/ss_devform.jpg Binary files differnew file mode 100644 index 0000000..a93e5a0 --- /dev/null +++ b/doc/img/ss_devform.jpg diff --git a/doc/img/ss_devices.jpg b/doc/img/ss_devices.jpg Binary files differnew file mode 100644 index 0000000..ecb3679 --- /dev/null +++ b/doc/img/ss_devices.jpg diff --git a/doc/img/ss_extprog.jpg b/doc/img/ss_extprog.jpg Binary files differnew file mode 100644 index 0000000..f5607de --- /dev/null +++ b/doc/img/ss_extprog.jpg diff --git a/doc/img/ss_mix.jpg b/doc/img/ss_mix.jpg Binary files differnew file mode 100644 index 0000000..8b4080f --- /dev/null +++ b/doc/img/ss_mix.jpg 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 Binary files differnew file mode 100644 index 0000000..5227b5a --- /dev/null +++ b/doc/img/ss_mixal.jpg diff --git a/doc/img/ss_split.jpg b/doc/img/ss_split.jpg Binary files differnew file mode 100644 index 0000000..66fd4a7 --- /dev/null +++ b/doc/img/ss_split.jpg diff --git a/doc/img/ss_symbols.jpg b/doc/img/ss_symbols.jpg Binary files differnew file mode 100644 index 0000000..6a0e827 --- /dev/null +++ b/doc/img/ss_symbols.jpg diff --git a/doc/img/ss_worddlg.jpg b/doc/img/ss_worddlg.jpg Binary files differnew file mode 100644 index 0000000..fc19000 --- /dev/null +++ b/doc/img/ss_worddlg.jpg 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 <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if !defined __STDC__ || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +# ifndef const +# define const +# endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include <gnu-versions.h> +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include <stdlib.h> +# include <unistd.h> +#endif /* GNU C library. */ + +#ifdef VMS +# include <unixlib.h> +# if HAVE_STRING_H - 0 +# include <string.h> +# endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +# ifdef HAVE_LIBINTL_H +# include <libintl.h> +# 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 <string.h> +# define my_index strchr +#else + +# if HAVE_STRING_H +# include <string.h> +# else +# if HAVE_STRINGS_H +# include <strings.h> +# 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 <jao@gnu.org> +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 <anp@cantv.net> +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 <anp@cantv.net> +- Upgrade to mdk-0.4 + +* Sun Jul 22 2001 Agustin Navarro <anp@cantv.net> +- Upgrade to mdk-0.4 + +* Thu Jun 21 2001 Agustin Navarro <anp@cantv.net> +- Upgrade to mdk-0.3.5 + +* Tue Jun 12 2001 Agustin Navarro <anp@cantv.net> +- Upgrade to mdk-0.3.4 + +* Sat Jun 09 2001 Agustin Navarro <anp@cantv.net> +- Upgrade to mdk-0.3.3 + +* Thu May 16 2001 Agustin Navarro <anp@cantv.net> +- Upgrade to 0.3.2 + +* Fri Mar 30 2001 Agustin Navarro <anp@cantv.net> +- 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 <pieter.pareit@skynet.be> +;; Maintainer: Pieter E.J. Pareit <pieter.pareit@skynet.be> +;; 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 <pking@pdq.net> +;; Maintainer: Philip Ellis King <pking@pdq.net> +;; Created: 12 Feb 2001 +;; Version: 0.2 +;; Keywords: tools + + +;;; Commentary: +;; mixvm.el provides an interface between mdk's mixvm and Emacs, +;; via gud. Place this file in your load-path, optionally adding +;; the following line to your .emacs file: +;; (autoload 'mixvm "mixvm" "mixvm/gud interaction" t) +;; Initiate a mdk/gud session with the command mixvm, gud will +;; reflect the current line in the source file buffer. + +;; (mixvm.el is based on a study of gdb, perldb, and pdb as found +;; in gud.el, and rubydb3x.el distributed with the source code to +;; the Ruby language. + +;;; Change Log: +;; Version 0.2 +;; Initial release + + +;;; Code: +(require 'gud) +(provide 'mixvm) + +;;; History of argument lists passed to mixvm. +(defvar gud-mixvm-history nil) + +;; rubydb3x provided good examples of xemacs/emacs +;; compatibility (not interested at the moment) +(defun gud-mixvm-massage-args (file args) + (cons "--emacs" args)) + +;; There's no guarantee that Emacs will hand the filter the entire +;; marker at once; it could be broken up across several strings. We +;; might even receive a big chunk with several markers in it. If we +;; receive a chunk of text which looks like it might contain the +;; beginning of a marker, we save it here between calls to the +;; filter. +(defvar gud-mixvm-marker-acc "") +(make-variable-buffer-local 'gud-mixvm-marker-acc) + +(defun gud-mixvm-marker-filter (string) + (setq gud-mixvm-marker-acc (concat gud-mixvm-marker-acc string)) + (let ((output "")) + + ;; Process all the complete markers in this chunk. + (while (string-match "\032\032mixvm:\\([^:]+\\):\\([0-9]+\\)" + gud-mixvm-marker-acc) + (setq + + ;; Extract the frame position from the marker. + gud-last-frame + (cons (substring gud-mixvm-marker-acc (match-beginning 1) (match-end 1)) + (string-to-int (substring gud-mixvm-marker-acc + (match-beginning 2) + (match-end 2)))) + + ;; Append any text before the marker to the output we're going + ;; to return - we don't include the marker in this text. + output (concat output + (substring gud-mixvm-marker-acc 0 (match-beginning 0))) + + ;; Set the accumulator to the remaining text. + gud-mixvm-marker-acc (substring gud-mixvm-marker-acc (match-end 0)))) + + ;; Does the remaining text look like it might end with the + ;; beginning of another marker? If it does, then keep it in + ;; gud-mixvm-marker-acc until we receive the rest of it. Since we + ;; know the full marker regexp above failed, it's pretty simple to + ;; test for marker starts. + ;; (note: \\' matches the end of the string (Perl's '$')) + (if (string-match "\032.*\\'" gud-mixvm-marker-acc) + (progn + ;; Everything before the potential marker start can be output. + (setq output (concat output (substring gud-mixvm-marker-acc + 0 (match-beginning 0)))) + + ;; Everything after, we save, to combine with later input. + (setq gud-mixvm-marker-acc + (substring gud-mixvm-marker-acc (match-beginning 0)))) + + (setq output (concat output gud-mixvm-marker-acc) + gud-mixvm-marker-acc "")) + + output)) + +;; See gdb for more comprehensive example +;; pek: it bugs me that this is run for EVERY interactive +;; mixvm command, should we cache some info somewhere? +(defun gud-mixvm-find-file (file) + (save-excursion + (let* ((buf (find-file-noselect file))) + (set-buffer buf) + (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 <stdio.h> +#include <stdlib.h> +#include "mixgtk.h" + +static gboolean initfile_ = TRUE; + +#ifdef MAKE_GUILE +# include <mixguile/mixguile.h> +# 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 <getopt.h> +#else +# include <lib/getopt.h> +#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 <stdio.h> +#include <string.h> + +#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 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="main_window"> + <property name="title" translatable="yes">gmixvm</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">650</property> + <property name="default_height">550</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="role">gmixvm-main</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + + <child> + <widget class="GtkVBox" id="main_vbox"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkMenuBar" id="mainmenubar"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="file"> + <property name="visible">True</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="file_menu"> + + <child> + <widget class="GtkImageMenuItem" id="file_open"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Load a MIX file</property> + <property name="label" translatable="yes">_Load...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_file_open_activate"/> + <accelerator key="O" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image432"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="edit"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Edit a MIXAL source file</property> + <property name="label" translatable="yes">_Edit...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_file_edit_activate"/> + <accelerator key="E" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image433"> + <property name="visible">True</property> + <property name="stock">gtk-justify-fill</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="compile"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Compile a MIXAL source file</property> + <property name="label" translatable="yes">_Compile...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_file_compile_activate"/> + <accelerator key="B" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image434"> + <property name="visible">True</property> + <property name="stock">gtk-execute</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator2"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="file_exit"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Exit application</property> + <property name="label" translatable="yes">E_xit</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_file_exit_activate"/> + <accelerator key="Q" modifiers="GDK_CONTROL_MASK | GDK_MOD1_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image435"> + <property name="visible">True</property> + <property name="stock">gtk-quit</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="debug"> + <property name="visible">True</property> + <property name="label" translatable="yes">De_bug</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="debug_menu"> + + <child> + <widget class="GtkImageMenuItem" id="debug_run"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Run program</property> + <property name="label" translatable="yes">_Run</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_debug_run_activate"/> + <accelerator key="R" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image436"> + <property name="visible">True</property> + <property name="stock">gtk-go-forward</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="debug_next"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Execute next instruction</property> + <property name="label" translatable="yes">_Next</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_debug_next_activate"/> + <accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image437"> + <property name="visible">True</property> + <property name="stock">gtk-goto-last</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="clear_breakpoints"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Clear all set breakpoints</property> + <property name="label" translatable="yes">_Clear breakpoints</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_clear_breakpoints_activate"/> + <accelerator key="C" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image438"> + <property name="visible">True</property> + <property name="stock">gtk-clear</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="symbols"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show the symbol table</property> + <property name="label" translatable="yes">_Symbols...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_symbols_activate"/> + <accelerator key="Y" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image439"> + <property name="visible">True</property> + <property name="stock">gtk-index</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="view1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Vie_w</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="view1_menu"> + + <child> + <widget class="GtkCheckMenuItem" id="show_toolbars"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Toolbars</property> + <property name="use_underline">True</property> + <property name="active">False</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id=" "> + <property name="visible">True</property> + <property name="label" translatable="yes">_Detached windows</property> + <property name="use_underline">True</property> + + <child internal-child="image"> + <widget class="GtkImage" id="image440"> + <property name="visible">True</property> + <property name="stock">gtk-dnd-multiple</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + + <child> + <widget class="GtkMenu" id=" _menu"> + + <child> + <widget class="GtkCheckMenuItem" id="detach_vm"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Virtual machine</property> + <property name="use_underline">True</property> + <property name="active">False</property> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="detach_source"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Source</property> + <property name="use_underline">True</property> + <property name="active">False</property> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="detach_dev"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Devices</property> + <property name="use_underline">True</property> + <property name="active">False</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="settings2"> + <property name="visible">True</property> + <property name="label" translatable="yes">S_ettings</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="settings2_menu"> + + <child> + <widget class="GtkImageMenuItem" id="fonts1"> + <property name="visible">True</property> + <property name="label" translatable="yes">Change _font</property> + <property name="use_underline">True</property> + + <child internal-child="image"> + <widget class="GtkImage" id="image441"> + <property name="visible">True</property> + <property name="stock">gtk-select-font</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + + <child> + <widget class="GtkMenu" id="fonts1_menu"> + + <child> + <widget class="GtkMenuItem" id="mix"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Virtual machine</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_mix_font_activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="mixal"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Source</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_mixal_font_activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="command_prompt"> + <property name="visible">True</property> + <property name="label" translatable="yes">Command _prompt</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_prompt_font_activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="command_log"> + <property name="visible">True</property> + <property name="label" translatable="yes">Command l_og</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_log_font_activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="devices"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Devices</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_devices_font_activate"/> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="symbol_list"> + <property name="visible">True</property> + <property name="label" translatable="yes">Symbol _list</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_symbols_font_activate" last_modification_time="Sun, 04 Jul 2004 23:03:55 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator4"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="all_fonts"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Change all fonts at once</property> + <property name="label" translatable="yes">_All</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_all_fonts_activate" last_modification_time="Sat, 03 Jul 2004 00:34:07 GMT"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="device_output1"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Change format of binary devices output</property> + <property name="label" translatable="yes">_Device output...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_devform_activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image442"> + <property name="visible">True</property> + <property name="stock">gtk-zoom-100</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="devices_dir"> + <property name="visible">True</property> + <property name="label" translatable="yes">De_vices dir...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_devdir_activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image443"> + <property name="visible">True</property> + <property name="stock">gtk-home</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="external_programs1"> + <property name="visible">True</property> + <property name="label" translatable="yes">E_xternal programs...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_external_programs_activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image444"> + <property name="visible">True</property> + <property name="stock">gtk-preferences</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkSeparatorMenuItem" id="separator3"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="save"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Save current settings</property> + <property name="label" translatable="yes">_Save</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_save_activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image445"> + <property name="visible">True</property> + <property name="stock">gtk-save</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkCheckMenuItem" id="save_on_exit"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Toogle save settings on exit</property> + <property name="label" translatable="yes">Save on _exit</property> + <property name="use_underline">True</property> + <property name="active">False</property> + <signal name="toggled" handler="on_save_on_exit_toggle"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="help"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="help_menu"> + + <child> + <widget class="GtkImageMenuItem" id="about"> + <property name="visible">True</property> + <property name="label" translatable="yes">_About...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_about_activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image446"> + <property name="visible">True</property> + <property name="stock">gtk-help</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHandleBox" id="tb_handle"> + <property name="visible">True</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <property name="handle_position">GTK_POS_LEFT</property> + <property name="snap_edge">GTK_POS_TOP</property> + + <child> + <widget class="GtkToolbar" id="main_toolbar"> + <property name="visible">True</property> + <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> + <property name="toolbar_style">GTK_TOOLBAR_ICONS</property> + <property name="tooltips">True</property> + <property name="show_arrow">True</property> + + <child> + <widget class="GtkToolButton" id="load_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Load MIX program</property> + <property name="label" translatable="yes">Open</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-open</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_file_open_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="compile_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Compile MIXAL source</property> + <property name="label" translatable="yes">Compile</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-execute</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_file_compile_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="edit_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Edit MIXAL source</property> + <property name="label" translatable="yes">Edit</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-justify-fill</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_file_edit_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="run_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Run</property> + <property name="label" translatable="yes">Run</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-go-forward</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_debug_run_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="step_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Next</property> + <property name="label" translatable="yes">Next</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-goto-last</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_debug_next_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="clear_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Clear breakpoints</property> + <property name="label" translatable="yes">Clear</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-clear</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_clear_breakpoints_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="symbols_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Symbol table</property> + <property name="label" translatable="yes">Symbols</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-index</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_symbols_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem2"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button28"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Device directory</property> + <property name="label" translatable="yes">Devdir</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-home</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_devdir_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button30"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Output format</property> + <property name="label" translatable="yes">Format</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-zoom-100</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_devform_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button31"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">External programs</property> + <property name="label" translatable="yes">Programs</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-properties</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_external_programs_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem8"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="dettach_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Detach window</property> + <property name="label" translatable="yes">Detach</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-dnd-multiple</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">False</property> + <signal name="clicked" handler="on_detach_clicked" last_modification_time="Tue, 29 Jun 2004 22:14:37 GMT"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="attach_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Attach all windows</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-dnd</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_attach_all_clicked" last_modification_time="Thu, 01 Jul 2004 22:00:12 GMT"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">3</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVPaned" id="main_panel"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">1</property> + + <child> + <widget class="GtkNotebook" id="main_notebook"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">True</property> + <property name="show_border">True</property> + <property name="tab_pos">GTK_POS_TOP</property> + <property name="scrollable">False</property> + <property name="enable_popup">False</property> + </widget> + <packing> + <property name="shrink">False</property> + <property name="resize">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="prompt_vbox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkScrolledWindow" id="mixlog_scrolledwindow"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTextView" id="command_log"> + <property name="visible">True</property> + <property name="editable">False</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_WORD</property> + <property name="cursor_visible">True</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">3</property> + <property name="right_margin">4</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="command_prompt"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Enter MIXVM command here</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <signal name="key_press_event" handler="on_command_prompt_key_press_event" after="yes"/> + <signal name="activate" handler="on_command_prompt_activate" last_modification_time="Sat, 19 Jun 2004 00:00:22 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="shrink">True</property> + <property name="resize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkStatusbar" id="main_statusbar"> + <property name="visible">True</property> + <property name="has_resize_grip">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="word_dialog"> + <property name="title" translatable="yes">Enter value</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">False</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="destroy" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="delete_event" handler="gtk_widget_hide"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area5"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="word_cancel"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + <signal name="clicked" handler="on_word_cancel_clicked" last_modification_time="Thu, 01 Jul 2004 22:25:09 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="word_reset"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-clear</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">False</property> + <property name="response_id">0</property> + <signal name="clicked" handler="on_word_reset_clicked" last_modification_time="Thu, 01 Jul 2004 22:28:00 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="word_ok"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + <signal name="clicked" handler="on_word_ok_clicked" last_modification_time="Thu, 01 Jul 2004 22:26:25 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkFixed" id="word_layout"> + <property name="border_width">5</property> + <property name="visible">True</property> + + <child> + <widget class="GtkEntry" id="word_decimal"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">28</property> + <signal name="changed" handler="on_word_dec_changed" after="yes" last_modification_time="Sun, 20 Jun 2004 23:47:46 GMT"/> + </widget> + <packing> + <property name="x">88</property> + <property name="y">64</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="word_b2"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">2</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">3</property> + <signal name="changed" handler="on_word_byte_changed" last_modification_time="Sun, 20 Jun 2004 23:20:10 GMT"/> + </widget> + <packing> + <property name="x">144</property> + <property name="y">32</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="word_b3"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_BUTTON_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">2</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">3</property> + <signal name="changed" handler="on_word_byte_changed" last_modification_time="Sun, 20 Jun 2004 23:20:28 GMT"/> + </widget> + <packing> + <property name="x">176</property> + <property name="y">32</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="word_b4"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">2</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">3</property> + <signal name="changed" handler="on_word_byte_changed" last_modification_time="Sun, 20 Jun 2004 23:20:57 GMT"/> + </widget> + <packing> + <property name="x">208</property> + <property name="y">32</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="word_b5"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">2</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">3</property> + <signal name="changed" handler="on_word_byte_changed" last_modification_time="Sun, 20 Jun 2004 23:21:18 GMT"/> + </widget> + <packing> + <property name="x">238</property> + <property name="y">32</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="word_b1"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">2</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">3</property> + <signal name="changed" handler="on_word_byte_changed" last_modification_time="Sun, 20 Jun 2004 23:19:50 GMT"/> + </widget> + <packing> + <property name="x">112</property> + <property name="y">32</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="word_sign"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_KEY_PRESS_MASK</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">1</property> + <property name="text" translatable="yes">+</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">2</property> + <signal name="changed" handler="on_word_sign_changed" last_modification_time="Sun, 20 Jun 2004 23:19:23 GMT"/> + </widget> + <packing> + <property name="x">88</property> + <property name="y">32</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label60"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Decimal</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">14</property> + <property name="y">68</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label61"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Bytes</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">15</property> + <property name="y">36</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="word_label"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Enter value</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">112</property> + <property name="y">8</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="about_dialog"> + <property name="title" translatable="yes">MDK</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <property name="modal">True</property> + <property name="default_width">250</property> + <property name="default_height">150</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child> + <widget class="GtkLayout" id="layout1"> + <property name="visible">True</property> + <property name="width">250</property> + <property name="height">150</property> + <property name="hadjustment">0 0 250 0 225 250</property> + <property name="vadjustment">0 0 150 0 135 150</property> + + <child> + <widget class="GtkLabel" id="label222"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">GNU MIX Development Kit</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">56</property> + <property name="y">24</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="version_label"> + <property name="width_request">52</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="label" translatable="yes">label223</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">96</property> + <property name="y">48</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label224"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes"> Copyright (C) 2001, 2002, 2003 , 2004 +Free Software Foundation, Inc. + +Please, send bug reports to +bug-mdk@gnu.org</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">24</property> + <property name="y">80</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="goto_dialog"> + <property name="title" translatable="yes">Go to memory cell</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox6"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area6"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="goto_cancel"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="goto_ok"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label225"> + <property name="visible">True</property> + <property name="label" translatable="yes">Go to address:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="goto_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">True</property> + </widget> + <packing> + <property name="padding">10</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkFontSelectionDialog" id="fontsel_dialog"> + <property name="border_width">4</property> + <property name="title" translatable="yes">Select Font</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child internal-child="cancel_button"> + <widget class="GtkButton" id="cancel_button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + + <child internal-child="apply_button"> + <widget class="GtkButton" id="apply_button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + + <child internal-child="ok_button"> + <widget class="GtkButton" id="ok_button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + </widget> + </child> + + <child internal-child="font_selection"> + <widget class="GtkFontSelection" id="fontselection1"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="preview_text" translatable="yes">abcdefghijk ABCDEFGHIJK</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> +</widget> + +<widget class="GtkDialog" id="devform_dialog"> + <property name="title" translatable="yes">Device output format</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="default_width">320</property> + <property name="default_height">140</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox8"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area8"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button37"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button38"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-apply</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-10</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button39"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkFixed" id="fixed2"> + <property name="visible">True</property> + + <child> + <widget class="GtkButton" id="devset_button"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Set all devices to current format</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">S_et all</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_devset_button_clicked"/> + </widget> + <packing> + <property name="x">233</property> + <property name="y">31</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label232"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Device</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">24</property> + <property name="y">10</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label233"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Format</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">24</property> + <property name="y">38</property> + </packing> + </child> + + <child> + <widget class="GtkComboBoxEntry" id="dev_combo"> + <property name="width_request">183</property> + <property name="height_request">25</property> + <property name="visible">True</property> + <property name="items" translatable="yes">tape0 +tape1 +tape2 +tape3 +tape4 +tape5 +tape6 +tape7 +disk0 +disk1 +disk2 +disk3 +disk4 +disk5 +disk6 +disk7</property> + <signal name="changed" handler="on_dev_combo_changed" last_modification_time="Wed, 23 Jun 2004 11:34:16 GMT"/> + </widget> + <packing> + <property name="x">90</property> + <property name="y">2</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="wordradio"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show output as MIX words</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Word</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="x">89</property> + <property name="y">34</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="decradio"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Show output as decimal numbers</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Decimal</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">wordradio</property> + <signal name="toggled" handler="on_decradio_toggled"/> + </widget> + <packing> + <property name="x">154</property> + <property name="y">34</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="external_dialog"> + <property name="title" translatable="yes">External programs</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox9"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area9"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button40"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button41"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkFixed" id="fixed3"> + <property name="visible">True</property> + + <child> + <widget class="GtkEntry" id="editor_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes">xterm -e vi %s</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="x">256</property> + <property name="y">12</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label234"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Editor command (e.g xterm -e vi %s)</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">8</property> + <property name="y">15</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFixed" id="fixed4"> + <property name="visible">True</property> + + <child> + <widget class="GtkEntry" id="mixasm_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes">mixasm %s</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="x">255</property> + <property name="y">4</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label235"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">MIX sssembler command (e.g. mixasm %s)</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="x">8</property> + <property name="y">8</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="symbols_dialog"> + <property name="title" translatable="yes">Symbol table</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">245</property> + <property name="default_height">265</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox10"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area10"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">0</property> + <signal name="clicked" handler="on_symbol_ok_clicked"/> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">0</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkHBox" id="hbox36"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image57"> + <property name="visible">True</property> + <property name="stock">gtk-close</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label1437"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Close</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow26"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="symbols_view"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">True</property> + <property name="reorderable">True</property> + <property name="enable_search">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="mixal_window"> + <property name="title" translatable="yes">MIXAL source</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">570</property> + <property name="default_height">225</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHandleBox" id="tb_handle"> + <property name="visible">True</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <property name="handle_position">GTK_POS_LEFT</property> + <property name="snap_edge">GTK_POS_TOP</property> + + <child> + <widget class="GtkToolbar" id="mixal_toolbar"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> + <property name="toolbar_style">GTK_TOOLBAR_ICONS</property> + <property name="tooltips">True</property> + <property name="show_arrow">True</property> + + <child> + <widget class="GtkToolButton" id="button14"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Run</property> + <property name="label" translatable="yes">Run</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-go-forward</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_debug_run_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button15"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Next</property> + <property name="label" translatable="yes">Step</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-goto-last</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_debug_next_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button16"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Clear breakpoints</property> + <property name="label" translatable="yes">Clear</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-clear</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_clear_breakpoints_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button18"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Symbol table</property> + <property name="label" translatable="yes">Symbols</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-index</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_symbols_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem7"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button22"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Source code font</property> + <property name="label" translatable="yes">Font</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-select-font</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_mixal_font_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem10"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="attach_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Attach window</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-dnd</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="mixal_container"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkStatusbar" id="mixal_statusbar"> + <property name="visible">True</property> + <property name="has_resize_grip">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="devices_window"> + <property name="title" translatable="yes">Devices</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">550</property> + <property name="default_height">250</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <signal name="delete_event" handler="on_window_hide"/> + <signal name="destroy_event" handler="on_window_hide"/> + <signal name="destroy" handler="on_window_hide"/> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHandleBox" id="tb_handle"> + <property name="visible">True</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <property name="handle_position">GTK_POS_LEFT</property> + <property name="snap_edge">GTK_POS_TOP</property> + + <child> + <widget class="GtkToolbar" id="devices_toolbar"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> + <property name="toolbar_style">GTK_TOOLBAR_ICONS</property> + <property name="tooltips">True</property> + <property name="show_arrow">True</property> + + <child> + <widget class="GtkToolButton" id="devdir_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Device directory</property> + <property name="label" translatable="yes">Directory</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-home</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_devdir_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="output_button"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Output format</property> + <property name="label" translatable="yes">Output</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-zoom-100</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_devform_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem11"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="button21"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Output font</property> + <property name="label" translatable="yes">Font</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-select-font</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_devices_font_activate"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem12"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="attach_button"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-dnd</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="dev_container"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="devdir_dialog"> + <property name="title" translatable="yes">Devices directory</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="delete_event" handler="gtk_widget_hide"/> + <signal name="destroy_event" handler="gtk_widget_hide"/> + <signal name="destroy" handler="gtk_widget_hide"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox11"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area11"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="devdir_cancel"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + <signal name="clicked" handler="on_devdir_cancel_clicked" last_modification_time="Tue, 22 Jun 2004 22:16:53 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="devdir_ok"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + <signal name="clicked" handler="on_devdir_ok_clicked" last_modification_time="Tue, 22 Jun 2004 22:18:04 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="border_width">25</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">11</property> + + <child> + <widget class="GtkLabel" id="label239"> + <property name="visible">True</property> + <property name="label" translatable="yes">Directory</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="devdir_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="devdir_browse"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-open</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_devdir_browse_clicked"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkWindow" id="mixvm_window"> + <property name="title" translatable="yes">Virtual machine</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">640</property> + <property name="default_height">268</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + + <child> + <widget class="GtkVBox" id="vbox8"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHandleBox" id="tb_handle"> + <property name="visible">True</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <property name="handle_position">GTK_POS_LEFT</property> + <property name="snap_edge">GTK_POS_TOP</property> + + <child> + <widget class="GtkToolbar" id="mixvm_toolbar"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property> + <property name="toolbar_style">GTK_TOOLBAR_ICONS</property> + <property name="tooltips">True</property> + <property name="show_arrow">True</property> + + <child> + <widget class="GtkToolButton" id="toolbutton2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Font</property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-select-font</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + <signal name="clicked" handler="on_mix_font_activate" last_modification_time="Wed, 30 Jun 2004 16:06:57 GMT"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + + <child> + <widget class="GtkSeparatorToolItem" id="separatortoolitem9"> + <property name="visible">True</property> + <property name="draw">True</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">False</property> + </packing> + </child> + + <child> + <widget class="GtkToolButton" id="attach_button"> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">True</property> + <property name="stock_id">gtk-dnd</property> + <property name="visible_horizontal">True</property> + <property name="visible_vertical">True</property> + <property name="is_important">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="homogeneous">True</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="mixvm_container"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="mixvm_widget"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="border_width">1</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">1</property> + + <child> + <widget class="GtkFrame" id="frame3"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkTable" id="table1"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">6</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">11</property> + + <child> + <widget class="GtkLabel" id="label97"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">A</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label100"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">I1</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label101"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">I2</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rA_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">19</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rI1_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rI2_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label98"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">X</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label102"> + <property name="width_request">16</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="label" translatable="yes">I3</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label103"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">I4</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">4</property> + <property name="right_attach">5</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label104"> + <property name="width_request">16</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="label" translatable="yes">I5</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">4</property> + <property name="right_attach">5</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label105"> + <property name="width_request">16</property> + <property name="height_request">16</property> + <property name="visible">True</property> + <property name="label" translatable="yes">I6</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">4</property> + <property name="right_attach">5</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label99"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">J</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rX_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">19</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rI4_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">5</property> + <property name="right_attach">6</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rI5_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">5</property> + <property name="right_attach">6</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rI6_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">5</property> + <property name="right_attach">6</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="rI3_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox22"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkEntry" id="rJ_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">9</property> + <signal name="button_press_event" handler="on_register_click"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label264"> + <property name="visible">True</property> + <property name="label" translatable="yes">Registers </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">2</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkFrame" id="frame5"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="border_width">1</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkRadioButton" id="greater_radio"> + <property name="border_width">2</property> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Greater</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">G</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_cmp_g_toggled"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="equal_radio"> + <property name="border_width">2</property> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Equal</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">E</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">greater_radio</property> + <signal name="toggled" handler="on_cmp_e_toggled"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="lesser_radio"> + <property name="border_width">2</property> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">Lesser</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">L</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">greater_radio</property> + <signal name="toggled" handler="on_cmp_l_toggled"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVSeparator" id="vseparator9"> + <property name="height_request">7</property> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="over_toggle"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Overflow</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_overflow_toggled" last_modification_time="Mon, 21 Jun 2004 11:44:04 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label266"> + <property name="visible">True</property> + <property name="label" translatable="yes">Flags </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">2</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + + <child> + <widget class="GtkFrame" id="frame6"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">1</property> + + <child> + <widget class="GtkEntry" id="loc_entry"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="visibility">True</property> + <property name="max_length">4</property> + <property name="text" translatable="yes">0</property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + <property name="width_chars">6</property> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="loc_arrow"> + <property name="visible">True</property> + <property name="tooltip" translatable="yes">View loc address</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="on_loc_arrow_clicked"/> + + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-jump-to</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">1</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label1323"> + <property name="visible">True</property> + <property name="label" translatable="yes">Location </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">2</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame2"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="label258"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Uptime:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="uptime_label"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">00000000</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label260"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Elapsed:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">3</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="elapsed_label"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">000000</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label261"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">Program:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">2</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="program_label"> + <property name="width_request">0</property> + <property name="height_request">0</property> + <property name="visible">True</property> + <property name="label" translatable="yes">000000</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">5</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label263"> + <property name="visible">True</property> + <property name="label" translatable="yes">Times </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">2</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">2</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame4"> + <property name="border_width">7</property> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkScrolledWindow" id="memory_scroll"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="memory_cells"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_BUTTON_PRESS_MASK</property> + <property name="headers_visible">True</property> + <property name="rules_hint">True</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label265"> + <property name="visible">True</property> + <property name="label" translatable="yes">Memory </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">2</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">3</property> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label1414"> + <property name="visible">True</property> + <property name="label" translatable="yes">MIX Virtual Machine </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">2</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="input_dialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">MIX Console input</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="has_separator">True</property> + <signal name="destroy_event" handler="gtk_widget_hide" last_modification_time="Wed, 23 Jun 2004 20:54:59 GMT"/> + <signal name="close" handler="gtk_widget_hide" last_modification_time="Wed, 23 Jun 2004 20:55:16 GMT"/> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox12"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area12"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="okbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label1438"> + <property name="visible">True</property> + <property name="label" translatable="yes">Enter up to 70 characters</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="input_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">70</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">True</property> + <property name="width_chars">70</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> 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 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd"> + +<glade-project> + <name>Mixgtk</name> + <program_name>mixgtk</program_name> + <pixmaps_directory>.</pixmaps_directory> + <gnome_support>FALSE</gnome_support> +</glade-project> 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 <gtk/gtk.h> +#include <mixlib/mix.h> + +/* 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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include <mixlib/mix.h> + +#ifdef HAVE_LIBHISTORY +# include <readline/history.h> +#endif + +#ifdef MAKE_GUILE +# include <mixguile/mixguile.h> +#endif + +#include <gdk/gdkkeysyms.h> +#include <mixlib/mix_vm_command.h> +#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 <mixlib/mix_vm.h> +#include <mixlib/mix_vm_command.h> +#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 <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#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 <mixlib/mix.h> +#include <mixlib/mix_config.h> + +/* 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <mixlib/mix_vm_command.h> +#include <mixlib/xmix_device.h> + +#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 <gtk/gtk.h> +#include <mixlib/mix_vm.h> +#include <mixlib/mix_device.h> + +/* 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 <mixlib/mix.h> +#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 <glib.h> +#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 <mixlib/mix_vm_command.h> +#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 <gtk/gtk.h> + +extern void +on_main_window_destroy (GtkWidget *w, gpointer data); + +extern void +on_file_open_activate (GtkWidget *w, gpointer data); + +extern void +on_file_exit_activate (GtkWidget *w, gpointer data); + +extern void +on_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 <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "mixgtk_widgets.h" +#include "mixgtk_input.h" + +enum { + MSG_, SIGN_, B1_, B2_, B3_, B4_, B5_, DEC_, RESET_, OK_, SIZE_ +}; + +static const gchar *WGT_NAMES_[SIZE_] = { + "word_label", "word_sign", "word_b1", "word_b2", "word_b3", + "word_b4", "word_b5", "word_decimal", "word_reset", "word_ok" +}; + +static GtkDialog *dialog_ = 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 <gdk/gdkkeysyms.h> + +/* 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 <mixlib/mix_types.h> + +/* 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 <stdlib.h> +#include <string.h> + +#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 <gtk/gtk.h> +#include <mixlib/mix_vm.h> +#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 <stdlib.h> +#include <mixlib/xmix_vm.h> +#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 <mixlib/mix_vm.h> +#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 <unistd.h> +#include <glade/glade.h> +#include <mixlib/mix.h> +#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 <gtk/gtk.h> +#include <mixlib/mix_vm.h> + +/* 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 <string.h> + +#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 <unistd.h> + +#include <mixlib/mix_config.h> +#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 <mixlib/mix.h> +#include <mixlib/mix_vm_command.h> +#include <guile/gh.h> + +/* 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 <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +#include <guile/gh.h> +#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 <mixlib/mix.h> +#include <mixlib/mix_vm_command.h> + +/* 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 <stdlib.h> +#include <stdio.h> +#include "mixguile.h" + + +#ifdef HAVE_GETOPT_LONG +# include <getopt.h> +#else +# include <lib/getopt.h> +#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 <string.h> + +#include <mixlib/mix.h> +#include <guile/gh.h> + +#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 <stdlib.h> +#include <stdio.h> + +#include <guile/gh.h> +#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 <libintl.h>. + 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 <libintl.h> + +#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 <locale.h> a NOP. We don't include <libintl.h> + as well because people using "gettext.h" will not include <libintl.h>, + and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> + is OK. */ +#if defined(__sun) +# include <locale.h> +#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 <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <errno.h> + + +#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 <config.h> +#else +# warning "config.h not found, package misconfigured." +# define PACKAGE "mdk" +# define VERSION "0.0" +#endif + +#ifdef HAVE_LOCALE_H +# include <locale.h> +#endif + +/* +#ifdef HAVE_GETTEXT +# include <libintl.h> +# define gettext_noop(String) (String) +#else +# include <intl/libgettext.h> +#endif +*/ +#include "gettext.h" + +#define _(String) gettext (String) +#define N_(String) gettext_noop (String) + +#include <glib.h> + +/* This function must be called before using the library */ +extern void +mix_init_lib (void); + +/* This function must be called for deallocating the lib resources + when it is no longer in use +*/ +extern void +mix_release_lib (void); + + +extern const char *MIX_GPL_LICENSE; + +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 <string.h> + +#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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#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 <stddef.h> +#include <stdio.h> +#include "mix.h" +#include "mix_types.h" + +/* + A mix device, which derives from mix_io_channel_t +*/ +typedef struct mix_device_t mix_device_t; + +/* + The device type +*/ +typedef enum { + mix_dev_TAPE_0, + mix_dev_TAPE_1, + mix_dev_TAPE_2, + mix_dev_TAPE_3, + mix_dev_TAPE_4, + mix_dev_TAPE_5, + mix_dev_TAPE_6, + mix_dev_TAPE_7, + mix_dev_DISK_0, + mix_dev_DISK_1, + mix_dev_DISK_2, + mix_dev_DISK_3, + mix_dev_DISK_4, + mix_dev_DISK_5, + mix_dev_DISK_6, + mix_dev_DISK_7, + mix_dev_CARD_RD, + mix_dev_CARD_WR, + mix_dev_PRINTER, + mix_dev_CONSOLE, + mix_dev_PAPER_TAPE, + mix_dev_INVALID +} mix_device_type_t; + +/* + The device io mode +*/ +typedef enum { + mix_dev_BIN, + mix_dev_CHAR +} mix_device_mode_t; + +/* + 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 <string.h> +#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; +%} + + +<*><<EOF>> { + CLEAN_UP (); + return MIX_EVAL_INTERN; +} + +<INITIAL>{ + {ws} /* eat whitespace */ + . { + if (!done && state == MIX_EVAL_OK) { + yypos -= yyleng; yyless (0); + yy_push_state (WEVAL); + } else { + CLEAN_UP (); + if (state == MIX_EVAL_OK) return (MIX_EVAL_SYNTAX); + data->errpos = yypos; + return state; + } + } + "\n" { + CLEAN_UP(); + if (state == MIX_EVAL_OK) + data->value = wexpr_val; + else + data->errpos = yypos; + return state; + } +} + +<WEVAL>{ + {number}"(" { + is_fp = TRUE; + wexpr_val_tmp = mix_word_new (atol (yytext)); + } + {number}")" { + glong val = atol (yytext); + if ( !is_fp ) { + RETURN_STATE (MIX_EVAL_MIS_PAREN); + } else if ( val < 0 || val > MIX_BYTE_MAX + || !mix_fspec_is_valid (mix_byte_new (val)) ) { + RETURN_STATE (MIX_EVAL_INV_FSPEC); + } else { + is_fp = FALSE; + wexpr_val = mix_word_store_field (mix_byte_new (val), + wexpr_val_tmp, + wexpr_val); + } + } + {number}/({ws}*\n)|[,()] { + wexpr_val = mix_word_new (atol (yytext)); + } + {expr}/({ws}*\n)|[,()] { + if (yytext[0] != '*') + { + yypos -= yyleng; + yyless (0); + } + else + { + yypos -= yyleng - 1; + expr_val = mix_short_to_word_fast (data->loc); + yyless (1); + } + yy_push_state (EVAL); + } + ,/{expr} /* eat comma if followed by expression */ + [\t\n ] { /* ok if not inside an f-part */ + if ( is_fp ) { + RETURN_STATE (MIX_EVAL_MIS_PAREN); + } + unput (yytext[yyleng-1]); --yypos; + done = TRUE; + yy_pop_state (); + } + . RETURN_STATE (MIX_EVAL_SYNTAX); +} + +<EVAL>{ + {binop}{digit}+ { + const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1; + mix_word_t value = mix_word_new (atol (s)); + expr_val = eval_binop_ (yytext, expr_val, value); + } + {binop}{symbol} { + const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1; + if ( !mix_symbol_table_is_defined (data->table, s) ) { + RETURN_STATE (MIX_EVAL_UNDEF_SYM); + } + expr_val = eval_binop_ (yytext, expr_val, + mix_symbol_table_value (data->table, s)); + } + {binop}"*" { + expr_val = eval_binop_ (yytext, expr_val, + mix_short_to_word_fast (data->loc)); + } + "*" yypos -= unput_word_ (mix_short_to_word_fast (data->loc)); + {number} expr_val = mix_word_new (atol (yytext)); + {symbol} { + if ( !mix_symbol_table_is_defined (data->table, yytext) ) { + RETURN_STATE (MIX_EVAL_UNDEF_SYM); + } + expr_val = mix_symbol_table_value (data->table, yytext); + } + [,)(\n\t ] { + unput (yytext[0]); --yypos; + yypos -= unput_word_ (expr_val); + yy_pop_state (); + } + + . RETURN_STATE (MIX_EVAL_SYNTAX); +} + + +%% + +static mix_word_t +eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y) +{ + mix_word_t result = MIX_WORD_ZERO; + switch (op[0]) + { + case '+': + result = mix_word_add (x,y); + break; + case '-': + result = mix_word_sub (x,y); + break; + case '*': + mix_word_mul (x, y, NULL, &result); + break; + case ':': + { + mix_word_t a; + mix_word_mul (x, 8, NULL, &a); + result = mix_word_add (a, y); + break; + } + case '/': + if ( strlen (op) > 1 && op[1] == '/' ) { + mix_word_div (x,MIX_WORD_ZERO,y, &result, NULL); + } else { + mix_word_div (MIX_WORD_ZERO, x, y, &result, NULL); + } + break; + default: + g_assert_not_reached (); + } + return result; +} + +static int +unput_word_ (mix_word_t word) +{ + gchar *value; + gint k, result; + value = g_strdup_printf ("%s%ld", + mix_word_is_negative (word)? "-":"+", + mix_word_magnitude (word)); + result = strlen (value); + for (k = result - 1; k >= 0; --k) + unput (value[k]); + g_free (value); + return result; +} diff --git a/mixlib/mix_file.c b/mixlib/mix_file.c new file mode 100644 index 0000000..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 <string.h> + +#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 <stdio.h> +#include "mix_types.h" + +/* mix_iochannel_t: an object for input/output of mix types */ +typedef struct mix_iochannel_t mix_iochannel_t; + +/* Cast to mix_iochannel_t */ +#define MIX_IOCHANNEL(file) (mix_iochannel_t *)(file) + +/* I/O channels can be created in different modes: */ +typedef enum { + mix_io_READ, /* read existing file */ + mix_io_WRITE, /* write new file */ + mix_io_RDWRT, /* read/write existing from beginning */ + mix_io_APPEND, /* append to existing or new file */ + mix_io_RAPPEND /* read from beginning, append to end */ +} mix_fmode_t; + +/* Create from a file handle */ +extern mix_iochannel_t * +mix_io_new (FILE *file); + +/* Delete */ +extern void +mix_io_delete (mix_iochannel_t *ch); + +/* Convert to a FILE * */ +extern FILE * +mix_io_to_FILE (mix_iochannel_t *ioc); + +/* Read/write from/to an iochannel */ +extern gboolean +mix_io_eof (mix_iochannel_t *ioc); + +extern gboolean +mix_io_is_ready (mix_iochannel_t *ioc); + +extern gboolean +mix_io_write_byte (mix_iochannel_t *ioc, mix_byte_t b); + +extern gboolean +mix_io_write_byte_array (mix_iochannel_t *ioc, const mix_byte_t *b, size_t s); + + +extern mix_byte_t +mix_io_read_byte (mix_iochannel_t *ioc); + +extern gboolean +mix_io_read_byte_array (mix_iochannel_t *ioc, mix_byte_t *b, size_t s); + + +extern gboolean +mix_io_write_word (mix_iochannel_t *ioc, mix_word_t w); + + +extern gboolean +mix_io_write_word_array (mix_iochannel_t *ioc, const mix_word_t *w, size_t s); + +extern mix_word_t +mix_io_read_word (mix_iochannel_t *ioc); + +extern gboolean +mix_io_read_word_array (mix_iochannel_t *ioc, mix_word_t *w, size_t s); + +extern gboolean +mix_io_write_short (mix_iochannel_t *ioc, mix_short_t w); + + +extern gboolean +mix_io_write_short_array (mix_iochannel_t *ioc, const mix_short_t *w, size_t s); + +extern mix_short_t +mix_io_read_short (mix_iochannel_t *ioc); + +extern gboolean +mix_io_read_short_array (mix_iochannel_t *ioc, mix_short_t *w, size_t s); + +extern gboolean +mix_io_write_char (mix_iochannel_t *ioc, mix_char_t c); + +extern mix_char_t +mix_io_read_char (mix_iochannel_t *ioc); + +extern gboolean +mix_io_write_word_array_as_char (mix_iochannel_t *ioc, + const mix_word_t *w, size_t s); + +extern gboolean +mix_io_read_word_array_as_char (mix_iochannel_t *ioc, + mix_word_t *w, size_t s); + + +#endif /* MIX_IOCHANNEL_H */ + diff --git a/mixlib/mix_parser.c b/mixlib/mix_parser.c new file mode 100644 index 0000000..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 <string.h> + +#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 <glib.h> +#include "mix_vm.h" + +/* The parser type */ +typedef struct mix_parser_t mix_parser_t; + +/* Create/destroy a mix_parser */ +extern mix_parser_t * +mix_parser_new (const gchar *in_file); + +extern void +mix_parser_delete (mix_parser_t *parser); + +/* Access source file name */ +extern const gchar * +mix_parser_src_file_base_name (const mix_parser_t *parser); + +extern const gchar * +mix_parser_src_file_extension (const mix_parser_t *parser); + +/* Compile a mix source file */ +/* compilation errors */ +typedef enum { + MIX_PERR_OK, /* no error */ + MIX_PERR_NOCOMP, /* file not yet compiled */ + MIX_PERR_INTERNAL, /* internal error */ + MIX_PERR_NOIN, /* unable to open input file */ + MIX_PERR_NOOUT, /* unable to open output file */ + MIX_PERR_UNEX_EOF, /* unexpected end of file */ + MIX_PERR_INV_LOC, /* invalid loc field */ + MIX_PERR_DUP_SYMBOL, /* duplicated symbol */ + MIX_PERR_LONG_SYMBOL, /* symbol name too long */ + MIX_PERR_NOOP, /* missing op field */ + MIX_PERR_UNEX_LOC, /* unexpected location symbol */ + MIX_PERR_INV_ADDRESS, /* invalid address field */ + MIX_PERR_INV_IDX, /* invalid index field */ + MIX_PERR_INV_FSPEC, /* invalid fspec */ + MIX_PERR_INV_OP, /* invalid operation */ + MIX_PERR_INV_EXPR, /* invalid expression */ + MIX_PERR_UNDEF_SYM, /* undefined symbol */ + MIX_PERR_MIS_PAREN, /* mismatched parenthesis */ + MIX_PERR_UNEX_FSPEC, /* unexpected f-spec */ + MIX_PERR_MIS_SYM, /* missing symbol name */ + MIX_PERR_SYM_INS, /* symbol has the same name as instruction */ + MIX_PERR_NOWRITE, /* failed code write */ + MIX_PERR_SHORT_ALF, /* short ALF operand */ + MIX_PERR_LONG_ALF, /* too long ALF operand */ + MIX_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 <ctype.h> +#include <string.h> + +#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); + +%} + + +<*><<EOF>> { + mix_parser_log_error (parser, MIX_PERR_UNEX_EOF, lineno, NULL, FALSE); + return MIX_PERR_UNEX_EOF; +} + +<INITIAL>{ + ^\*.* /* eat comments */ + . { + if ( end ) return parser->status; + yyless (0); + BEGIN (LOC); + } + \n { + ++lineno; + if ( end ) return parser->status; + } +} + +<LOC>{ + {ws}+ BEGIN (OP); /* LOC field is empty */ + {locsymbol} { /* manage local symbol */ + loc = get_ploc_ (parser); + lsymbol = g_strdup (yytext); + if ( lsymbol == NULL ) { + mix_parser_log_error (parser, MIX_PERR_INTERNAL, lineno, NULL, FALSE); + return MIX_PERR_INTERNAL; + } + BEGIN (OP); + } + {locsymbol}/({ws}+EQU) {/* local symbol with value */ + loc = get_ploc_ (parser); + symbol = g_strdup (yytext); + lsymbol = g_strdup (yytext); + if ( symbol == NULL || lsymbol == NULL) { + mix_parser_log_error (parser, MIX_PERR_INTERNAL, lineno, NULL, FALSE); + return MIX_PERR_INTERNAL; + } + symbol[1] = 'B'; /* this will be referred as nB afterwards */ + BEGIN (OP); + } + {flocsymbol}|{blocsymbol} RETURN_ERROR (MIX_PERR_UNEX_LOC, yytext); + {symbol}/({ws}+EQU) { /* store symbol name for future definition */ + symbol = g_strdup (yytext); + if ( symbol == NULL ) { + mix_parser_log_error (parser, MIX_PERR_INTERNAL, lineno, NULL, FALSE); + return MIX_PERR_INTERNAL; + } + BEGIN (OP); + } + {symbol} { /* define a new symbol */ + mix_parser_err_t err; + if ( mix_get_id_from_string (yytext) != mix_INVALID_INS ) + mix_parser_log_error (parser, MIX_PERR_SYM_INS, lineno, yytext, TRUE); + if ( (err = mix_parser_define_symbol_here (parser,yytext)) != MIX_PERR_OK ) + mix_parser_log_error (parser, err, lineno, yytext, FALSE); + BEGIN (OP); + } + . RETURN_ERROR (MIX_PERR_INV_LOC, yytext); + \n ++lineno; /* empty line */ +} + +<OP>{ + {ws}+ /* eat leading whitespace */ + \n RETURN_ERROR (MIX_PERR_NOOP, NULL); + ORIG{ws}+ BEGIN (ORIG); + CON{ws}+ BEGIN (CON); + EQU{ws}+ BEGIN (EQU); + END{ws}+ BEGIN (END); + ALF{ws}+\"{mixchar}{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); +} + + +<ORIG>{ + {number}{ws}*\n | + {number}{ws}+.*\n { + mix_word_t value = mix_word_new (atol (yytext)); + parser->loc_count = mix_word_to_short_fast (value); + ++lineno; + BEGIN (INITIAL); + } +} + +<CON>{ + {number}{ws}*\n | + {number}{ws}+.*\n { + mix_word_t value = mix_word_new (atol (yytext)); + ADD_RAW (value, TRUE); + } +} + +<EQU>{ + {number}{ws}*\n | + {number}{ws}+.*\n { + mix_word_t value; + gint def; + if ( symbol == NULL ) RETURN_ERROR (MIX_PERR_MIS_SYM, NULL); + value = mix_word_new (atol (yytext)); + def = mix_parser_define_symbol_value (parser, symbol, value); + if ( def == MIX_SYM_DUP ) RETURN_ERROR (MIX_PERR_DUP_SYMBOL, symbol); + if ( def == MIX_SYM_LONG ) RETURN_ERROR (MIX_PERR_LONG_SYMBOL, symbol); + ++lineno; + BEGIN (INITIAL); + } +} + +<END>{ + {number}{ws}*\n | + {number}{ws}+.*\n { + parser->start = mix_short_new (atol (yytext)); + parser->end = parser->loc_count; + end = TRUE; + if ( parser->status == MIX_PERR_NOCOMP ) parser->status = MIX_PERR_OK; + return parser->status; + } +} + +<ORIG,CON,EQU,END>{ + {wexpr} ENTER_WEVAL (0); + . RETURN_ERROR (MIX_PERR_INV_OP, yytext); +} + + +<ADDRESS,INDEX,FSPEC>{locsymbol} RETURN_ERROR (MIX_PERR_UNEX_LOC, yytext); + +<ADDRESS>{ + =/[+-]?{number}= lsf = TRUE; + =/{expr}= lsf = TRUE; + ={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); +} + + +<INDEX>{ + {number}[\n(\t ] { + int end = yytext[yyleng-1]; + ins.index = mix_byte_new (atol (yytext)); + if ( end == '\n' ) + ADD_INS (); + else if ( end == '(' ) + BEGIN (FSPEC); + else + { /* eat rest of line (comment) */ + while ( (end = input()) != '\n' && end != EOF ) ; + if ( end == '\n' ) ADD_INS (); + else RETURN_ERROR (MIX_PERR_UNEX_EOF, NULL); + } + } + {expr}/[\n(\t ] ENTER_EVAL (); + \n { + mix_parser_log_error (parser, MIX_PERR_INV_IDX, lineno++, NULL, FALSE); + RESET (); + BEGIN (INITIAL); + } + . RETURN_ERROR (MIX_PERR_INV_IDX, yytext); +} + +<FSPEC>{ + {number}")"(({ws}+.*\n)|\n) { + glong val = atol (yytext); + if ( val < 0 || val > MIX_BYTE_MAX ) + RETURN_ERROR (MIX_PERR_INV_FSPEC, NULL); + if ( ins.opcode != mix_opMOVE + && ( ins.opcode < mix_opJBUS || ins.opcode > mix_opJXx ) + && !mix_fspec_is_valid (mix_byte_new (val)) ) + RETURN_ERROR (MIX_PERR_INV_FSPEC, NULL); + if ( nof ) + mix_parser_log_error (parser, MIX_PERR_INV_FSPEC, + lineno, _("ignored"), TRUE); + else + { + ins.fspec = mix_byte_new (val); + 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); +} + + +<EVAL>{ + {binop}{digit}+ { + const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1; + mix_word_t value = mix_word_new (atol (s)); + expr_val = eval_binop_ (yytext, expr_val, value); + } + {binop}{symbol} { + const gchar *s = ( yytext[1] == '/' ) ? yytext+2 : yytext+1; + if ( !mix_symbol_table_is_defined (parser->symbol_table, s) ) { + mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, lineno, s, FALSE); + yy_pop_state (); + } + expr_val = eval_binop_ (yytext, expr_val, + mix_symbol_table_value (parser->symbol_table, s)); + } + {binop}"*" { + expr_val = eval_binop_ (yytext, expr_val, + mix_short_to_word_fast (parser->loc_count)); + } + "*" unput_word_ (mix_short_to_word_fast (parser->loc_count)); + {number} expr_val = mix_word_new (atol (yytext)); + {symbol} { + if ( !mix_symbol_table_is_defined (parser->symbol_table, yytext) ) { + mix_parser_log_error (parser, MIX_PERR_UNDEF_SYM, lineno, yytext, FALSE); + yy_pop_state (); + } + expr_val = mix_symbol_table_value (parser->symbol_table, yytext); + } + [,)(=\n\t ] unput (yytext[0]); unput_word_ (expr_val); yy_pop_state (); + . RETURN_ERROR (MIX_PERR_INV_EXPR, yytext); +} + +<WEVAL>{ + {number}"(" { + is_fp = TRUE; + wexpr_val_tmp = mix_word_new (atol (yytext)); + } + {number}")" { + glong val = atol (yytext); + if ( !is_fp ) { + mix_parser_log_error (parser, MIX_PERR_MIS_PAREN, lineno, NULL, FALSE); + yy_pop_state (); + } + if ( val < 0 || val > MIX_BYTE_MAX + || !mix_fspec_is_valid (mix_byte_new (val)) ) { + mix_parser_log_error (parser, MIX_PERR_INV_FSPEC, lineno, NULL, FALSE); + yy_pop_state (); + } + is_fp = FALSE; + wexpr_val = mix_word_store_field (mix_byte_new (val), wexpr_val_tmp, + wexpr_val); + } + {number}/[,()\n\t ] wexpr_val = mix_word_new (atol (yytext)); + {expr}/[,()\n\t ] ENTER_EVAL (); + ,/{expr} /* eat comma if followed by expression */ + [=\n\t ] { /* ok if not inside an f-part */ + if ( is_fp ) { + mix_parser_log_error (parser, MIX_PERR_MIS_PAREN, lineno, NULL, FALSE); + yy_pop_state (); + } + unput (yytext[yyleng-1]); + unput_word_ (wexpr_val); + yy_pop_state (); + } + . RETURN_ERROR (MIX_PERR_INV_EXPR, NULL); +} + +%% + +static mix_word_t +eval_binop_ (const gchar *op, mix_word_t x, mix_word_t y) +{ + mix_word_t result = MIX_WORD_ZERO; + switch (op[0]) + { + case '+': + result = mix_word_add (x,y); + break; + case '-': + result = mix_word_sub (x,y); + break; + case '*': + mix_word_mul (x, y, NULL, &result); + break; + case ':': + { + mix_word_t a; + mix_word_mul (x, 8, NULL, &a); + result = mix_word_add (a, y); + break; + } + case '/': + if ( strlen (op) > 1 && op[1] == '/' ) { + mix_word_div (x,MIX_WORD_ZERO,y, &result, NULL); + } else { + mix_word_div (MIX_WORD_ZERO, x, y, &result, NULL); + } + break; + default: + g_assert_not_reached (); + } + return result; +} + +static void +unput_word_ (mix_word_t word) +{ + gchar *value; + gint k; + value = g_strdup_printf ("%s%ld", + mix_word_is_negative (word)? "-":"+", + mix_word_magnitude (word)); + for (k = strlen (value) - 1; k >= 0; --k) + unput (value[k]); + g_free (value); +} diff --git a/mixlib/mix_src_file.c b/mixlib/mix_src_file.c new file mode 100644 index 0000000..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 <ctype.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include "mix_src_file.h" + +/* the MIXAL source file type */ +struct mix_src_file_t +{ + gchar *path; /* the path to the disk file */ + GPtrArray *lines; /* an array of the file lines */ + guint lineno; /* the number of lines */ +}; + +/* format a source line */ +static gchar * +format_line_ (gchar *line) +{ + const gchar *label, *op, *rest; + gint k = 0; + + if (!line) return line; + if (line[0] == '*' || strlen(line) == 0) + return g_strdup (line); + + if (isspace (line[0])) + { + label = " "; + while (line[k] && isspace (line[k])) ++k; + } + else + { + label = line; + while (line[k] && !isspace (line[k])) ++k; + while (line[k] && isspace (line[k])) ++k; + } + + if (line[k]) + { + line[k - 1] = 0; + op = line + k; + while (line[k] && !isspace (line[k])) ++k; + while (line[k] && isspace (line[k])) ++k; + line[k - 1] = 0; + rest = (line[k]) ? line + k: ""; + } + else + { + op = rest = ""; + } + + + return g_strdup_printf ("%-11s %-5s %s", label, op, rest); +} + +/* load the source file lines into memory */ +static gboolean +load_file_ (mix_src_file_t *file) +{ + mix_file_t *mf = mix_file_new_with_def_ext (file->path, + mix_io_READ, + MIX_SRC_DEFEXT); + if (mf != NULL) + { + enum {BUFFER_SIZE = 256}; + static gchar BUFFER[BUFFER_SIZE]; + + FILE *f = mix_file_to_FILE (mf); + file->lines = g_ptr_array_new (); + file->lineno = 0; + + while (fgets (BUFFER, BUFFER_SIZE, f) == BUFFER) + { + g_ptr_array_add (file->lines, (gpointer) format_line_ (BUFFER)); + file->lineno++; + } + + mix_file_delete (mf); + return TRUE; + } + return FALSE; +} + +/* create a new src file from an existing disk file */ +mix_src_file_t * +mix_src_file_new_for_read (const gchar *path) +{ + mix_src_file_t *result = g_new (mix_src_file_t, 1); + result->lines = NULL; + result->path = g_strdup (path); + result->lineno = 0; + return result; +} + +/* destroy a src file object */ +void +mix_src_file_delete (mix_src_file_t *src) +{ + g_return_if_fail (src != NULL); + if (src->lines) g_ptr_array_free (src->lines, TRUE); + g_free (src->path); + g_free (src); +} + +/* get the source file path */ +const gchar * +mix_src_file_get_path (const mix_src_file_t *src) +{ + g_return_val_if_fail (src != NULL, NULL); + return src->path; +} + +/* get a given line of the source file */ +const gchar * +mix_src_file_get_line (const mix_src_file_t *src, guint lineno) +{ + g_return_val_if_fail (src != NULL, NULL); + if (src->lines == NULL && !load_file_ ((mix_src_file_t*)src)) + return NULL; + if (lineno > src->lineno || lineno == 0) + return NULL; + return (gchar *)g_ptr_array_index (src->lines, lineno - 1); +} + +/* get the total no. of lines in the file */ +guint +mix_src_file_get_line_no (const mix_src_file_t *src) +{ + g_return_val_if_fail (src != NULL, 0); + if (src->lines == NULL && !load_file_ ((mix_src_file_t*)src)) + return 0; + return src->lineno; +} + diff --git a/mixlib/mix_src_file.h b/mixlib/mix_src_file.h new file mode 100644 index 0000000..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 <ctype.h> /* isdigit */ +#include <string.h> + +#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 <stdio.h> +#include "mix_types.h" + +/* A symbol table shall be implemented as a hash table */ +typedef GHashTable mix_symbol_table_t ; + +/* Maximum length of stored symbols */ +#define MIX_SYM_MAX_LEN 10 + +/* Create an empty table */ +extern mix_symbol_table_t * +mix_symbol_table_new (void); + +/* Create a table and populate it with the contents of a table stored + in -file- using mix_symbol_table_print (table, MIX_SYM_LINE, file) +*/ +extern mix_symbol_table_t * +mix_symbol_table_new_from_file (FILE *file); + + +/* Delete a table */ +extern void +mix_symbol_table_delete (mix_symbol_table_t *table); + +/* add/remove symbols from other table */ +extern gboolean +mix_symbol_table_merge_table (mix_symbol_table_t *table, + const mix_symbol_table_t *from); + +extern gboolean +mix_symbol_table_substract_table (mix_symbol_table_t *table, + const mix_symbol_table_t *other); + +/* Add/remove symbols one by one */ +/* possible outcomes: */ +enum { + MIX_SYM_FAIL, /* attempt failed */ + MIX_SYM_OK, + MIX_SYM_DUP, /* duplicated symbol */ + MIX_SYM_LONG /* symbol too long: only MIX_SYM_MAX_LEN chars used */ +}; + +extern gint +mix_symbol_table_add (mix_symbol_table_t *table, + const gchar *sym, mix_word_t value); + +#define mix_symbol_table_remove(table, sym) \ + g_hash_table_remove (table, sym) + + +/* Add or modify symbol if it exists */ +extern gint +mix_symbol_table_insert (mix_symbol_table_t *table, + const gchar *sym, mix_word_t new_value); + +/* Add or modify symbol if it exists, without 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 <limits.h> +#include <ctype.h> +#include "mix_types.h" + + +/*------------------------ initialisation stuff ------------------------*/ +/* flag telling whether a field spec is valid */ +static gboolean is_bad_field_[MIX_BYTE_MAX + 1]; +/* shift associated with a fspec */ +static guint shift_[MIX_BYTE_MAX + 1]; +/* mask associated with a fspec */ +static glong mask_[MIX_BYTE_MAX + 1]; + +/* maps from gchar's to mix_char_t */ +#define NONP_ (guchar)('?') +static mix_char_t ascii_to_mix_char_[UCHAR_MAX + 1]; +static guchar mix_char_to_ascii_[MIX_CHAR_MAX + 1] = { + ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '~', '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 <stdio.h> +#include "mix.h" + +/* Initialisation function to be called before using the other + * functions in this file + */ +extern void +mix_init_types(void); + + +/*----------------- m_byte_t --------------------------------------------*/ +/* MIX byte type */ +typedef guint8 mix_byte_t; + +/* Maximum value stored in an mix_byte_t */ +#define MIX_BYTE_MAX ((1L << 6) - 1) + +/* Zero mix byte */ +#define MIX_BYTE_ZERO ((mix_byte_t)0) + +/* Create a mix_byte_t from any native type */ +#define mix_byte_new(x) ((mix_byte_t)((x) & MIX_BYTE_MAX )) + +/* Operations */ +/* Addition */ +#define mix_byte_add(x,y) mix_byte_new((x) + (y)) +/* Substraction */ +#define mix_byte_sub(x,y) mix_byte_new((x) - (y)) +/* Product */ +#define mix_byte_mul(x,y) mix_byte_new((x) * (y)) +/* Quotient */ +#define mix_byte_div(x,y) mix_byte_new((x) / (y)) + + +/*----------------- mix_char_t --------------------------------------------*/ +/* MIX char type: chars are coded in MIX from 0 to MIX_CHAR_MAX */ +typedef guint8 mix_char_t; + +#define MIX_CHAR_MAX 55 + +/* Conversions for mix_char_t's */ +#define mix_char_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 <readline/history.h> +#endif + +#ifdef HAVE_LIBREADLINE +# include <readline/readline.h> +#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 <stdio.h> +#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 <unistd.h> +#include "xmix_vm.h" +#include "mix_vm_dump.h" + +/* Create/destroy a dump context */ +mix_dump_context_t * +mix_dump_context_new(FILE *fd, mix_address_t begin, mix_address_t end, + guint32 options) +{ + mix_dump_context_t *result = NULL; + + g_return_val_if_fail (fd != NULL, NULL); + + if ( begin > end ) begin = end; + if ( end >= MEM_CELLS_NO_ ) end = MEM_CELLS_NO_; + + result = g_new (mix_dump_context_t,1); + result->options = options; + result->begin = begin; + result->end = end; + result->channel = fd; + + return result; +} + +void +mix_dump_context_delete (mix_dump_context_t *dc) +{ + g_return_if_fail (dc != NULL); + g_free (dc); +} + +/* Use the dump context */ +#define WORD_FMT_ "%s %02d %02d %02d %02d %02d (%010ld)" +#define SHORT_FMT_ "%s %02d %02d (%04d)" +#define WORD_SIGN_(w) mix_word_is_negative (w)? "-":"+" +#define SHORT_SIGN_(s) mix_short_is_negative (s)? "-":"+" +#define WORD_ABS_(w) mix_word_magnitude (w) +#define SHORT_ABS_(s) mix_short_magnitude (s) +#define WORD_BYTE_(w,i) mix_byte_new (mix_word_magnitude (w)>>(6*(5-i))) +#define SHORT_BYTE_(s,i) mix_byte_new (mix_short_magnitude (s)>>(6*(2-i))) +#define WORD_ARGS_(w) WORD_SIGN_ (w), WORD_BYTE_ (w,1), WORD_BYTE_ (w,2), \ + WORD_BYTE_ (w,3), WORD_BYTE_ (w,4), WORD_BYTE_ (w,5), WORD_ABS_ (w) +#define SHORT_ARGS_(s) SHORT_SIGN_ (s), SHORT_BYTE_ (s,1), SHORT_BYTE_ (s,2), \ + SHORT_ABS_ (s) + +void +mix_vm_dump (const mix_vm_t *vm, const mix_dump_context_t *dc) +{ + guint j, i; + FILE *f; + + g_return_if_fail (vm != NULL); + g_return_if_fail (dc != NULL); + + f = dc->channel; + + if ( (dc->options & MIX_DUMP_rA) == MIX_DUMP_rA ) + { + mix_word_t rA = get_rA_ (vm); + fprintf (f, "rA: " WORD_FMT_ "\n", WORD_ARGS_ (rA)); + } + + if ( (dc->options & MIX_DUMP_rX) == MIX_DUMP_rX ) + { + mix_word_t rX = get_rX_ (vm); + fprintf (f, "rX: " WORD_FMT_ "\n", WORD_ARGS_ (rX)); + } + + if ( (dc->options & MIX_DUMP_rJ) == MIX_DUMP_rJ ) + { + mix_short_t rJ = get_rJ_ (vm); + fprintf (f, "rJ: " SHORT_FMT_ "\n", SHORT_ARGS_ (rJ)); + } + + for (j = 0, i = 0; j < IREG_NO_; ++j) + { + if ( (dc->options & (MIX_DUMP_rI1<<j)) == (MIX_DUMP_rI1<<j) ) + { + mix_short_t rI = mix_word_to_short_fast (get_rI_ (vm, j+1)); + fprintf (f, "rI%d: " SHORT_FMT_ "\t", j+1, SHORT_ARGS_ (rI)); + i++; + } + if ( i%2 == 0 && i != 0 ) fprintf (f, "\n"); + } + + if ( i%2 == 1 ) fprintf (f, "\n"); + + if ( (dc->options & MIX_DUMP_OVER) == MIX_DUMP_OVER ) + { + fprintf (f, _("Overflow: %s\n"), get_over_ (vm)? "T":"F"); + } + + if ( (dc->options & MIX_DUMP_CMP) == MIX_DUMP_CMP ) + { + const gchar *val = "?"; + switch (get_cmp_ (vm)) + { + case mix_LESS: + val = "L"; + break; + case mix_GREAT: + val = "G"; + break; + case mix_EQ: + val = "E"; + break; + default: + g_assert_not_reached (); + break; + } + fprintf (f, _("Cmp: %s\n"), val); + } + + if ( (dc->options & MIX_DUMP_CELLS) == MIX_DUMP_CELLS ) + { + for (j = dc->begin; j < dc->end; ++j) + { + mix_word_t cell = get_cell_ (vm,j); + fprintf (f, "%04d: " WORD_FMT_ "\n", j, WORD_ARGS_ (cell)); + } + } + fflush (f); +} + diff --git a/mixlib/mix_vm_dump.h b/mixlib/mix_vm_dump.h new file mode 100644 index 0000000..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 <stdio.h> +#include "mix_vm.h" + +/* Dump context: a structure defining the properties of dumping */ +typedef struct mix_dump_context_t mix_dump_context_t; +struct mix_dump_context_t +{ + /* flags activating dumps (see enum below) */ + guint32 options; + /* range of addresses dumped: [begin,end) */ + mix_address_t begin; + mix_address_t end; + /* IO channel for dumping */ + FILE *channel; +}; + +/* Flags for activating dumps */ +#define MIX_DUMP_NONE 0 +#define MIX_DUMP_rA 1 +#define MIX_DUMP_rX (1<<1) +#define MIX_DUMP_rJ (1<<2) +#define MIX_DUMP_rI1 (1<<3) +#define MIX_DUMP_rI2 (1<<4) +#define MIX_DUMP_rI3 (1<<5) +#define MIX_DUMP_rI4 (1<<6) +#define MIX_DUMP_rI5 (1<<7) +#define MIX_DUMP_rI6 (1<<8) +#define MIX_DUMP_rIa MIX_DUMP_rI1|MIX_DUMP_rI2|MIX_DUMP_rI3 \ + |MIX_DUMP_rI4|MIX_DUMP_rI5|MIX_DUMP_rI6 +#define MIX_DUMP_rALL MIX_DUMP_rA|MIX_DUMP_rX|MIX_DUMP_rJ|MIX_DUMP_rIa +#define MIX_DUMP_OVER (1<<9) +#define MIX_DUMP_CMP (1<<10) +#define MIX_DUMP_CELLS (1<<11) +#define MIX_DUMP_ALL MIX_DUMP_rALL|MIX_DUMP_OVER|MIX_DUMP_CMP|MIX_DUMP_CELLS +#define MIX_DUMP_ALL_NOMEM MIX_DUMP_rALL|MIX_DUMP_OVER|MIX_DUMP_CMP + +/* Default output channel (stdout) */ +#define MIX_DUMP_DEF_CHANNEL (stdout) + +/* Create/destroy a dump context */ +extern mix_dump_context_t * +mix_dump_context_new (FILE *fd, mix_address_t begin, mix_address_t end, + guint32 options); + +extern void +mix_dump_context_delete(mix_dump_context_t *dc); + +/* Modify an existing dump context */ +#define mix_dump_context_add_opt(dc,opt) ((dc)->options |= (opt)) +#define mix_dump_context_del_opt(dc,opt) ((dc)->options &= ~(opt)) +#define mix_dump_context_set_opt(dc,opt) ((dc)->options = (opt)) +#define mix_dump_context_range(dc,first,last) \ +do { \ + (dc)->begin = first; \ + (dc)->end = last; \ +} while (FALSE) + + +/* Use the dump context */ +extern void +mix_vm_dump(const mix_vm_t *vm, const mix_dump_context_t *dc); + + +#endif /* MIX_VM_DUMP_H */ + diff --git a/mixlib/testsuite/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 <stdlib.h> +#include <mix_device.h> + +/* Define VERBOSE_TEST if you want to get prints of the test */ +/* #define VERBOSE_TEST */ +#include "test.h" + +static int S_ = MIX_CHAR_MAX +1; + +int +main (int argc, char **argv) +{ + mix_device_t *console; + size_t s; + mix_word_t **block; + mix_char_t mchars[S_]; + gchar chars[S_]; + int i, j; + int bno; + + + INIT_TEST; + + console = mix_device_new (mix_dev_CONSOLE); + s = mix_device_block_size (console); + bno = S_/(s*5); + if (bno == 0) bno = 1; + + block = g_new (mix_word_t *, bno); + for (i = 0; i < bno; ++i) + block[i] = g_new (mix_word_t, s); + + for (i = 0; i < S_; ++i) { + chars[i] = mix_char_to_ascii (i); + mchars[i] = mix_ascii_to_char (chars[i]); + g_assert (mchars[i] == i); + } + + for (i = 0; i < bno; ++i) { + for (j = 0; j < s; ++j) { + int n = i*s + 5*j; + if (n < S_) + block[i][j] = mix_bytes_to_word (mchars + n, 5); + else + block[i][j] = 0; + } + } + + for (i = 0; i < bno; ++i) { + mix_device_write (console, block[i]); + } + + + return EXIT_SUCCESS; +} diff --git a/mixlib/testsuite/mix_eval_t.c b/mixlib/testsuite/mix_eval_t.c new file mode 100644 index 0000000..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 <stdlib.h> +#include <mix_eval.h> +/* Define VERBOSE_TEST if you want to get prints of the test */ +/* #define VERBOSE_TEST */ +#include "test.h" + +typedef struct test_case_t +{ + const gchar *expr; + gint value; + mix_eval_result_t result; +} test_case_t; + +#define ok_case(exp,val) {exp, val, MIX_EVAL_OK} +#define err_case(exp,err) {exp, 0, err} + +typedef struct sym_val_t +{ + const gchar *sym; + mix_word_t value; +} sym_val_t; + +#define new_symbol(sym,val) {sym, mix_word_new (val)} + +int +main(int argc, char **argv) +{ + size_t k; + mix_eval_t *eval; + mix_short_t loc = mix_short_new (30); + sym_val_t symbols[] = { + new_symbol ("s0", 43), + new_symbol ("s1", -1234), + new_symbol ("s2", 0), + new_symbol ("s3", -20), + new_symbol (NULL, 0) + }; + + test_case_t cases[] = { + ok_case ("2343", 2343), + ok_case ("-890", -890), + ok_case ("15+1015", 1030), + ok_case ("1-481", -480), + ok_case ("2300/10", 230), + ok_case ("24*3", 72), + ok_case ("2:5", 21), + ok_case ("1//3", 357913941), + ok_case ("12+*", 42), + ok_case ("***", 900), + ok_case ("1:3*2-4", 18), + ok_case ("-1+5*20/6", 13), + ok_case ("-1000(0,2),1", 1), + ok_case ("s0-s2*3", 129), + ok_case ("s3**", -600), + ok_case ("s3(3:5)", 20), + ok_case ("-s1", 1234), + ok_case ("s1/10+s0", 166), + err_case ("foo", MIX_EVAL_UNDEF_SYM), + err_case ("11--2", MIX_EVAL_SYNTAX), + err_case ("s2*foo*3", MIX_EVAL_UNDEF_SYM), + err_case ("12/32),1", MIX_EVAL_MIS_PAREN), + err_case ("2000(88)", MIX_EVAL_INV_FSPEC), + ok_case (NULL, 0) + }; + + INIT_TEST; + g_print ("Entering mix_eval test..."); + eval = mix_eval_new (); + + for (k = 0; symbols[k].sym; ++k) + mix_eval_set_symbol (eval, symbols[k].sym, symbols[k].value); + + for (k = 0; cases[k].expr; ++k) { + mix_eval_result_t r = cases[k].result, s; + g_print ("Evaluating \"%s\" = %d ...", + cases[k].expr, cases[k].value); + + s = mix_eval_expression_with_loc (eval, cases[k].expr, loc); + g_assert (s == r); + if ( s == MIX_EVAL_OK ) { + mix_word_print (mix_eval_value (eval), "... "); + g_print ("\n"); + g_assert (mix_eval_value (eval) == mix_word_new(cases[k].value)); + } else { + g_print ("\n------->%s, at pos %d\n", + mix_eval_last_error_string (eval), + mix_eval_last_error_pos (eval)); + } + } + mix_eval_delete (eval); + + return EXIT_SUCCESS; +} + + diff --git a/mixlib/testsuite/mix_ins_t.c b/mixlib/testsuite/mix_ins_t.c new file mode 100644 index 0000000..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 <stdlib.h> +#include <mix_ins.h> + +/* Define VERBOSE_TEST if you want to get prints of the test */ +/* #define VERBOSE_TEST */ +#include "test.h" + + +int +main(int argc, const char**argv) +{ + mix_word_t words[6]; + mix_ins_t ins[3]; + guint k; + + INIT_TEST; + + g_print("\n...ok.\nTesting mix_ins_id_t properties...\n"); + for ( k = 0; k < mix_INVALID_INS; ++k ) + { + mix_opcode_t c = mix_get_opcode_from_id(k); + mix_fspec_t f = mix_get_fspec_from_id(k); + mix_ins_id_t id = mix_get_ins_id(c,f); + + g_print("%02d:%s (%1d:%1d), ", + c, mix_get_string_from_id(k), + mix_fspec_left(f), mix_fspec_right(f)); + if ( (k+1)%3 == 0 ) g_print("\n"); + + g_assert(id==k); + } + + g_print("\n...ok.\nTesting mix_ins_t properties...\n"); + for ( k = 1; k < mix_INVALID_INS; ++k ) + { + g_print("%d ",k); + mix_ins_fill_from_id(ins[0], k); + g_assert(mix_ins_id_from_ins(ins[0]) == k); + ins[0].address = 0x0123; + ins[0].index = mix_I2; + words[2] = mix_ins_to_word(ins); + g_assert(ins[0].address == mix_get_ins_address(words[2])); + g_assert(ins[0].index == mix_get_ins_index(words[2])); + g_assert(ins[0].fspec == mix_get_ins_fspec(words[2])); + g_assert(ins[0].opcode == mix_get_ins_opcode(words[2])); + g_assert(mix_word_to_ins(words[2],ins+1) == k); + g_assert(ins[0].address == ins[1].address); + g_assert(ins[0].index == ins[1].index); + g_assert(ins[0].fspec == ins[1].fspec); + g_assert(ins[0].opcode == ins[1].opcode); + } + + g_print("\n...ok.\n"); + + + + return EXIT_SUCCESS; +} diff --git a/mixlib/testsuite/mix_parser_t.c b/mixlib/testsuite/mix_parser_t.c new file mode 100644 index 0000000..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 <stdlib.h> +#include <mix_parser.h> + +/* Define VERBOSE_TEST if you want to get prints of the test */ +/* #define VERBOSE_TEST */ +#include "test.h" + +static const gchar * const FILES_[] = { "test1" , "taocp145" +}; + +static const size_t FILE_NO_ = sizeof(FILES_)/sizeof(FILES_[0]); + +static void +test_code_(const gchar *name) +{ + mix_parser_t *parser = mix_parser_new(name); + mix_parser_err_t err; + mix_code_file_t *code; + mix_ins_desc_t ins; + + g_assert(parser); + err = mix_parser_compile(parser); + if ( err != MIX_PERR_OK ) { + g_print(mix_parser_err_string(err)); + g_print("\n"); + } + g_assert(err == MIX_PERR_OK); + err = mix_parser_write_code(parser, name, FALSE); + code = mix_code_file_new_read(name); + g_assert(code); + g_message("%s: Version: %d.%d", name, mix_code_file_major_version(code), + mix_code_file_minor_version(code)); + mix_short_print(mix_code_file_get_start_addr(code), "Start address: "); + g_print("\n"); + while ( mix_code_file_get_ins(code, &ins) ) { + mix_ins_t i; + mix_word_to_ins_uncheck(ins.ins, i); + mix_short_print(ins.address, "addr: "); + g_print(" : "); + mix_ins_print(&i); + g_print("\n"); + } + + mix_parser_delete(parser); + mix_code_file_delete(code); +} + +int +main(int argc, char **argv) +{ + size_t k; + + INIT_TEST; + + for (k = 0; k < FILE_NO_; ++k) + // test_code_(FILES_[k]); + ; + + + return EXIT_SUCCESS; +} + diff --git a/mixlib/testsuite/mix_types_t.c b/mixlib/testsuite/mix_types_t.c new file mode 100644 index 0000000..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 <stdlib.h> +#include <mix_types.h> + +/* Define VERBOSE_TEST if you want to get prints of the test */ +/* #define VERBOSE_TEST */ +#include "test.h" + +/* compare two words */ +static gboolean +word_compare_(mix_word_t w1, mix_word_t w2) +{ + if ( mix_word_magnitude(w1) == 0 ) + return ( mix_word_magnitude(w2) == 0 ); + else + return ( w1 == w2 ); +} + + +/* create a word from an array of bytes and check the result */ +static void +test_word_from_bytes_(mix_word_t *word, + mix_byte_t *bytes, + unsigned byteno, + const char *message) +{ + mix_byte_t r; + unsigned int k; + + *word = mix_bytes_to_word(bytes,byteno); + mix_word_print(*word,message); + g_print("\n"); + for ( k = 5-byteno; k < 5; ++k ) { + PRINT_BYTE(r = mix_word_get_byte(*word,k+1)); + g_print(" (k = %d)\n",k); + g_assert( r == bytes[k-5+byteno] ); + } +} + + +/* test field access */ +static void +test_field_access_(mix_fspec_t l, mix_fspec_t r, + mix_word_t from, mix_word_t to) +{ + mix_fspec_t f = mix_fspec_new(l,r); + mix_word_t result; + + PRINT_BYTE(l); g_print(", "); + PRINT_BYTE(r); g_print(", "); + PRINT_BYTE(f); g_print("\n "); + mix_word_print(from, "from: "); + mix_word_print(to, " to: "); + g_assert( mix_fspec_left(f) == l ); + g_assert( mix_fspec_right(f) == r ); + result = mix_word_set_field(f,from,to); + mix_word_print(result,"\n\tresult: "); + g_assert( mix_word_get_field(f,from) == mix_word_get_field(f,result) ); + g_print("\n"); +} + +/* test word addition */ +static void +test_word_add_(mix_word_t w1, mix_word_t w2) +{ + mix_word_t r; + + r = mix_word_add(w1,w2); + mix_word_print(w1,"\n"); + mix_word_print(w2,NULL); + mix_word_print(r," = "); + g_assert( word_compare_(mix_word_sub(r,w1), w2) ); + g_assert( word_compare_(mix_word_sub(r,w2), w1) ); + /* while asserting the following, take into account that 0 != -0 + for mix words, although they are logically equivalent + */ + g_assert( word_compare_(mix_word_sub(w1,r), mix_word_negative(w2)) ); + g_assert( word_compare_(mix_word_sub(w2,r), mix_word_negative(w1)) ); + g_assert( word_compare_(mix_word_add(w2,w1), r) ); +} + +/* test word multiplication */ +static void +test_word_mul_(mix_word_t w1, mix_word_t w2) +{ + mix_word_t h, l, q, r = 0; + mix_word_mul(w1,w2,&h,&l); + mix_word_print(w1,"\n"); + mix_word_print(w2,"*"); + mix_word_print(h,"\n ="); + mix_word_print(l,NULL); + if ( w1 != 0 ) { + g_assert( mix_word_div(h,l,w1,&q,&r) == FALSE ); + g_assert( mix_word_magnitude(r) == 0 ); + g_assert( q == w2 ); + } else { + g_assert( mix_word_magnitude(l) == 0 && mix_word_magnitude(h) == 0 ); + } + if ( w2 != 0 ) { + g_assert( mix_word_div(h,l,w2,&q,&r) == FALSE ); + g_assert( mix_word_magnitude(r) == 0 ); + g_assert( q == w1 ); + } else { + g_assert( mix_word_magnitude(l) == 0 && mix_word_magnitude(h) == 0 ); + } + +} + +/* test word division */ +static void +test_word_div_(mix_word_t h, mix_word_t l, mix_word_t by) +{ + mix_word_t q,r; + gboolean overflow; + + overflow = mix_word_div(h,l,by,&q,&r); + + mix_word_print(h,"\n\n"); + mix_word_print(l,NULL); + mix_word_print(by,"\n div by "); + + if ( !overflow ) { + mix_word_t h1, l1, h2; + mix_word_print(q,"\n q = "); + mix_word_print(r," r = "); + mix_word_mul(by,q,&h1,&l1); + mix_word_add_and_carry(l1,r,&h2,&l1); + h1 = mix_word_add(h1,h2); + g_assert( mix_word_magnitude(r) < mix_word_magnitude(by) ); + g_assert( word_compare_(h1,h) ); + g_assert( mix_word_magnitude(l1) == mix_word_magnitude(l) ); + } else + g_print("\n\t = overflow"); + +} + +static void +test_mix_char_(void) +{ + mix_char_t mchar; + guchar achar; + guint k; + g_print("\nTesting mix_char_t. Table of mix_chars:\n"); + + for (k = 0; k < MIX_CHAR_MAX + 1; ++k) { + mchar = k; + achar = mix_char_to_ascii(mchar); + g_print("%02d: %c, ", k, achar); + if ( (k+1)%5 == 0 ) g_print("\n"); + g_assert( mchar == mix_ascii_to_char(achar) ); + } + + g_print("\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 <stdlib.h> +/* #define VERBOSE_TEST */ +#include "test.h" +#include "mix_vm.h" +#include "mix_vm_dump.h" + +typedef struct +{ + mix_word_t rA_b, rA_a; + mix_word_t rX_b, rX_a; + mix_short_t rJ_b, rJ_a; + mix_short_t rI_b[6], rI_a[6]; + gboolean over_b, over_a; + mix_cmpflag_t cmp_b, cmp_a; + mix_address_t begin, end; + mix_word_t *cells_b, *cells_a; + const mix_ins_t *ins; +} test_desc_t; + +static void +set_cells_(test_desc_t *t, mix_address_t begin, mix_address_t end) +{ + g_assert(begin <= end); + t->begin = begin; + t->end = end; + t->cells_b = g_new(mix_word_t,end-begin); + t->cells_a = g_new(mix_word_t,end-begin); +} + +static void +free_cells_(test_desc_t *t) +{ + g_assert(t); + g_free(t->cells_a); + g_free(t->cells_b); + t->cells_a = t->cells_b = NULL; + t->begin = t->end = 0; +} + + +static void +fill_test_desc_(test_desc_t *t, const mix_vm_t *vm, const mix_ins_t *ins) +{ + guint k; + g_assert(t); + g_assert(vm); + + t->rA_b = t->rA_a = mix_vm_get_rA(vm); + t->rX_b = t->rX_a = mix_vm_get_rX(vm); + t->rJ_b = t->rJ_a = mix_vm_get_rJ(vm); + for ( k = 0; k < 6; ++k ) + t->rI_b[k] = t->rI_a[k] = mix_vm_get_rI(vm,k+1); + t->cmp_b = t->cmp_a = mix_vm_get_cmpflag(vm); + t->over_b = t->over_a = mix_vm_get_overflow(vm); + + for (k = 0; k < t->end-t->begin; ++k) + t->cells_a[k] = t->cells_b[k] = + mix_vm_get_addr_contents(vm,t->begin+k); + t->ins = ins; +} + + +static void +run_test_(test_desc_t *t, mix_vm_t *vm, mix_dump_context_t *dc) +{ + guint k; + g_assert(t); + g_assert(vm); + + mix_vm_set_rA(vm, t->rA_b); + mix_vm_set_rX(vm, t->rX_b); + mix_vm_set_rJ(vm, t->rJ_b); + for (k = 0; k < 6; ++k) mix_vm_set_rI(vm, k+1, t->rI_b[k]); + for (k = t->begin; k < t->end; ++k) + mix_vm_set_addr_contents(vm, k, t->cells_b[k-t->begin]); + mix_vm_set_cmpflag(vm, t->cmp_b); + mix_vm_set_overflow(vm, t->over_b); + + mix_ins_print(t->ins); + if (dc) { + mix_dump_context_range(dc, t->begin, t->end); + mix_vm_dump(vm,dc); + } + k = mix_vm_exec_ins(vm, t->ins); + if (dc) mix_vm_dump(vm, dc); + g_assert(k == TRUE); + g_assert(mix_vm_get_rA(vm) == t->rA_a); + g_assert(mix_vm_get_rX(vm) == t->rX_a); + for (k = 0; k < 6; ++k) g_assert(mix_vm_get_rI(vm, k+1) == t->rI_a[k]); + g_assert(mix_vm_get_cmpflag(vm) == t->cmp_a); + g_assert(mix_vm_get_overflow(vm) == t->over_a); + for (k = t->begin; k < t->end; ++k) + g_assert(mix_vm_get_addr_contents(vm, k) == t->cells_a[k-t->begin]); +} + + + +static void +test_arithmetics_(mix_vm_t *vm, mix_dump_context_t *dc) +{ + test_desc_t test; + mix_ins_t ins; + + g_print("\nTesting arithmetic instructions...\n"); + mix_vm_reset(vm); + mix_ins_fill_from_id(ins,mix_ADD); + ins.index = 0; + ins.address = 1000; + mix_vm_set_rA(vm,mix_word_new_b(19,18,1,2,22)); + mix_vm_set_addr_contents(vm,1000,mix_word_new_b(1,36,5,0,50)); + set_cells_(&test,1000,1001); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(20,54,6,3,8); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins,mix_SUB); + mix_vm_set_rA(vm,mix_word_new_bn(19,18,0,0,9)); + mix_vm_set_addr_contents(vm,1000,mix_word_new_bn(31,16,2,22,0)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(11,62,2,21,55); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins,mix_MUL); + mix_vm_set_rA(vm,mix_word_new_b(1,1,1,1,1)); + mix_vm_set_addr_contents(vm,1000, mix_word_new_b(1,1,1,1,1)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(0,1,2,3,4); + test.rX_a = mix_word_new_b(5,4,3,2,1); + run_test_(&test, vm, dc); + + ins.fspec = mix_fspec_new(1,1); + mix_vm_set_rA(vm,mix_word_new_bn(0,0,0,1,48)); + mix_vm_set_addr_contents(vm,1000,mix_word_new_bn(2,16,2,22,0)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = MIX_WORD_MINUS_ZERO; + test.rX_a = mix_word_new_bn(0,0,0,3,32); + run_test_(&test, vm, dc); + + mix_vm_set_rA(vm,mix_word_new_bn(0,0,0,1,48)); + mix_vm_set_addr_contents(vm,1000,mix_word_new_b(2,0,34,33,1)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = MIX_WORD_MINUS_ZERO; + test.rX_a = mix_word_new_bn(0,0,0,3,32); + run_test_(&test, vm, dc); + + ins.fspec = mix_fspec_new(0,5); + mix_vm_set_rA(vm,mix_word_new_bn(50,0,1,48,4)); + mix_vm_set_addr_contents(vm,1000,mix_word_new_bn(2,0,0,0,0)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(1,36,0,3,32); + test.rX_a = mix_word_new_b(8,0,0,0,0); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins,mix_DIV); + mix_vm_set_rA(vm,MIX_WORD_ZERO); + mix_vm_set_rX(vm,mix_word_new_b(0,0,0,0,17)); + mix_vm_set_addr_contents(vm,1000, mix_word_new_b(0,0,0,0,3)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(0,0,0,0,5); + test.rX_a = mix_word_new_b(0,0,0,0,2); + run_test_(&test, vm, dc); + + mix_vm_set_rA(vm,MIX_WORD_ZERO); + mix_vm_set_rX(vm,mix_word_new_bn(0,0,0,0,17)); + mix_vm_set_addr_contents(vm,1000, mix_word_new_b(0,0,0,0,3)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(0,0,0,0,5); + test.rX_a = mix_word_new_b(0,0,0,0,2); + run_test_(&test, vm, dc); + + mix_vm_set_rA(vm, MIX_WORD_MINUS_ZERO); + mix_vm_set_rX(vm, mix_word_new_b(19,19,0,3,1)); + mix_vm_set_addr_contents(vm,1000, mix_word_new_bn(0,0,0,2,0)); + fill_test_desc_(&test,vm,&ins); + test.rA_a = mix_word_new_b(0,9,41,32,1); + test.rX_a = mix_word_new_bn(0,0,0,1,1); + run_test_(&test, vm, dc); + + free_cells_(&test); +} + +static void +test_shift_(mix_vm_t *vm, mix_dump_context_t *dc) +{ + test_desc_t test; + mix_ins_t ins; + + g_print("Testing shift instructions...\n"); + mix_vm_reset(vm); + set_cells_(&test,0,0); + fill_test_desc_(&test,vm,&ins); + mix_ins_fill_from_id(ins,mix_SRAX); + ins.index = 0; + ins.address = 1; + test.rA_b = mix_word_new_b(1,2,3,4,5); + test.rX_b = mix_word_new_bn(6,7,8,9,10); + test.rA_a = mix_word_new_b(0,1,2,3,4); + test.rX_a = mix_word_new_bn(5,6,7,8,9); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_SLA); + ins.address = 2; + fill_test_desc_(&test, vm, &ins); + test.rA_a = mix_word_new_b(2,3,4,0,0); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_SRC); + ins.address = 4; + fill_test_desc_(&test, vm, &ins); + test.rA_a = mix_word_new_b(6,7,8,9,2); + test.rX_a = mix_word_new_bn(3,4,0,0,5); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_SRA); + ins.address = 2; + fill_test_desc_(&test, vm, &ins); + test.rA_a = mix_word_new_b(0,0,6,7,8); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_SLC); + ins.address = 501; + fill_test_desc_(&test, vm, &ins); + test.rA_a = mix_word_new_b(0,6,7,8,3); + test.rX_a = mix_word_new_bn(4,0,0,5,0); + run_test_(&test, vm, dc); +} + +static void +test_spc_(mix_vm_t *vm, mix_dump_context_t *dc) +{ + test_desc_t test; + mix_ins_t ins; + + g_print("Testing special instructions...\n"); + mix_vm_reset(vm); + set_cells_(&test,0,0); + fill_test_desc_(&test,vm,&ins); + mix_ins_fill_from_id(ins,mix_NUM); + ins.index = 0; + ins.address = 0; + test.rA_b = mix_word_new_bn(0,0,31,32,39); + test.rX_b = mix_word_new_b(37,57,47,30,30); + test.rA_a = mix_word_negative(12977700); + test.rX_a = test.rX_b; + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_INCA); + ins.address = 1; + fill_test_desc_(&test, vm, &ins); + test.rA_a = mix_word_negative(12977699); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_CHAR); + fill_test_desc_(&test, vm, &ins); + test.rA_a = mix_word_new_bn(30,30,31,32,39); + test.rX_a = mix_word_new_b(37,37,36,39,39); + run_test_(&test, vm, dc); + + mix_ins_fill_from_id(ins, mix_HLT); + fill_test_desc_(&test, vm, &ins); + run_test_(&test, vm, dc); + g_assert(mix_vm_is_halted(vm)); + +} + +static void +test_move_(mix_vm_t *vm, mix_dump_context_t *dc) +{ + test_desc_t test; + mix_ins_t ins; + guint k; + + g_print("Testing move instruction...\n"); + mix_vm_reset(vm); + set_cells_(&test,0,10); + fill_test_desc_(&test,vm,&ins); + mix_ins_fill_from_id(ins,mix_MOVE); + + ins.index = 0; + ins.address = 0; + ins.fspec = 5; + for ( k = 0; k < 5; ++k ) + test.cells_b[k] = test.cells_a[k+5] = test.cells_a[k] =mix_word_new(100*k); + + test.rI_b[0] = 5; + test.rI_a[0] = 10; + run_test_(&test,vm,dc); + + free_cells_(&test); +} + + + +static void +test_load_(mix_vm_t *vm, mix_dump_context_t *dc) +{ + test_desc_t test; + mix_ins_t ins; + mix_ins_id_t ids[4] = {mix_LDA, mix_LDX, mix_LDAN, mix_LDXN}; + mix_word_t r_a[14] = { + mix_word_new_bn(1,16,3,5,4), + mix_word_new_b(1,16,3,5,4), + mix_word_new_b(0,0,3,5,4), + mix_word_new_bn(0,0,1,16,3), + mix_word_new_b(0,0,0,0,5), + mix_word_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 <glib.h> +#include <mix.h> + +#define PRINT_BYTE(byte) g_print("%s = %02d",#byte,byte) + +#ifdef VERBOSE_TEST /* get printed information */ +#define INIT_TEST \ + do { g_set_print_handler(NULL); mix_init_lib(); } while(FALSE); +#else /* no printed information */ +static void +dummy_print_f_(const gchar *m) +{ + /* no output */ +} +#define INIT_TEST \ +do { g_set_print_handler(dummy_print_f_); mix_init_lib(); } while(FALSE); +#endif /* VERBOSE_TEST */ + + +#endif /* TEST_H */ diff --git a/mixlib/xmix_device.c b/mixlib/xmix_device.c new file mode 100644 index 0000000..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 <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "xmix_io.h" + +const char *io_OPENTYPE_[5] = { "r", "w", "w+", "a", "a+" }; + + +/* initialise a mix_iochannel from a file descriptor */ +gboolean +io_init_from_fdesc_(mix_iochannel_t *ioc, int fdesc) +{ + FILE *file; + mix_fmode_t mode; + int flags = fcntl(fdesc, F_GETFL); + + if ( (flags&O_RDONLY) == O_RDONLY ) + mode = mix_io_READ; + else if ( (flags&O_WRONLY) == O_WRONLY ) + mode = mix_io_WRITE; + else if ( (flags&O_RDWR) == O_RDWR ) + mode = mix_io_RDWRT; + else + return FALSE; + + file = fdopen(fdesc, fmode_to_type_(mode)); + g_return_val_if_fail(file != NULL, FALSE); + 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 <stdio.h> +#include "mix_io.h" + +/* the actual definition of mix_iochannel_t */ +struct mix_iochannel_t +{ + FILE *file; +}; + + +extern const char * io_OPENTYPE_[5]; + +#define fmode_to_type_(mode) ( (mode) < 6 ? io_OPENTYPE_[(mode)]:NULL ) + +/* initialisation */ +extern gboolean +io_init_from_fdesc_(mix_iochannel_t *ioc, int fdesc); + +#define io_init_from_file_(ioc,f) (ioc)->file = f + +#define io_close_(ioc) fclose((ioc)->file) + +/* write/read data */ +#define write_data_(ioc,data,no) \ + ( (no) == fwrite((const void*)(data), sizeof(*(data)), (no), (ioc)->file) ) + +#define read_data_(ioc,data,no) \ + ( (no) == fread((void*)(data), sizeof(*(data)), (no), (ioc)->file) ) + +/* state */ +#define is_eof_(ioc) ( feof((ioc)->file) != 0 ) +#define is_ready_(ioc) ( ferror((ioc)->file) == 0 ) + +/* conversions */ +#define io_get_FILE_(ioc) (MIX_IOCHANNEL(ioc))->file + + +#endif /* XMIX_IOCHANNEL_H */ + diff --git a/mixlib/xmix_parser.h b/mixlib/xmix_parser.h new file mode 100644 index 0000000..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 <string.h> + +#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 <stdarg.h> +#include <stdio.h> + +#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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#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; k<pos; ++k) fputc (arg[k], dis->err); + fputc ('\n', dis->err); + for (k = 0; k<pos; ++k) fputc (' ', dis->err); + for (k = pos; k < len; ++k) fputc (arg[k], dis->err); + fprintf (dis->err, _("\nEvaluation error: %s\n"), + mix_eval_last_error_string (dis->eval)); + return FALSE; + } +} + +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 <mixlib/mix.h> + +#include <stdlib.h> +#include <stdio.h> + +#ifdef HAVE_GETOPT_LONG +# include <getopt.h> +#else +# include <lib/getopt.h> +#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 <mixlib/mix.h> +#include <stdlib.h> +#include <stdio.h> +#include <mixlib/mix_parser.h> +#include "mixasm_comp.h" + +int +mix_asm_compile(const gchar *src, const gchar *out, gboolean use_list, + const gchar *list, gboolean debug) +{ + int result = EXIT_SUCCESS; + mix_parser_t *parser; + mix_parser_err_t error; + + if ( (parser = mix_parser_new(src)) == NULL ) + { + fprintf(stderr, _("*** Unable to open source file %s\n"), src); + return EXIT_FAILURE; + } + if ( mix_parser_compile(parser) == MIX_PERR_OK ) + { + guint k; + if ( ( k = mix_parser_warning_count(parser) ) != 0 ) + fprintf(stderr, _("(%d warning(s))\n"), k); + if ( (error = mix_parser_write_code(parser, out, debug)) != MIX_PERR_OK ) + { + fprintf(stderr, _("*** Error writing output code file: %s\n"), + mix_parser_err_string(error)); + result = EXIT_FAILURE; + } + else if ( use_list + && (error = mix_parser_write_listing(parser, list)) != + MIX_PERR_OK) + { + fprintf(stderr, _("*** Error writing listing file: %s\n"), + mix_parser_err_string(error)); + result = EXIT_FAILURE; + } + } + else + { + fprintf(stderr, _("(%d warning(s), %d error(s))\n"), + mix_parser_warning_count(parser), mix_parser_err_count(parser)); + result = EXIT_FAILURE; + } + + mix_parser_delete(parser); + return result; +} + + diff --git a/mixutils/mixasm_comp.h b/mixutils/mixasm_comp.h new file mode 100644 index 0000000..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 <glib.h> + +extern int +mix_asm_compile(const gchar *src, const gchar *out, gboolean use_list, + const gchar *list, gboolean debug); + + + +#endif /* MIXASM_COMP_H */ + diff --git a/mixutils/mixvm.c b/mixutils/mixvm.c new file mode 100644 index 0000000..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 <mixlib/mix.h> +#include <mixlib/mix_vm.h> +#include <mixlib/mix_vm_dump.h> + +#include <stdlib.h> +#include <stdio.h> + +#ifdef HAVE_GETOPT_LONG +# include <getopt.h> +#else +# include <lib/getopt.h> +#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 <mixlib/mix.h> + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include <mixlib/mix.h> + +#ifdef HAVE_LIBREADLINE +# include <readline/readline.h> +# include <readline/history.h> +# 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 <mixlib/mix_vm.h> +#include <mixlib/mix_vm_dump.h> +#include <mixlib/mix_eval.h> +#include <mixlib/mix_src_file.h> +#include <mixlib/mix_vm_command.h> + +#ifdef MAKE_GUILE +# include <mixguile/mixguile.h> +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 <mixlib/mix_config.h> +#include <mixlib/mix_vm_command.h> + +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 <stdio.h> +#include <string.h> + +#include <mixlib/mix.h> +#include <mixlib/mix_config.h> +#include <mixlib/mix_vm.h> +#include <mixlib/mix_device.h> +#include <mixlib/mix_vm_dump.h> + +#ifdef MAKE_GUILE +#include <mixguile/mixguile.h> +#endif + +#include "mixvm_command.h" +#include "mixvm_loop.h" + +#ifdef HAVE_LIBHISTORY +# include <readline/history.h> +#else +# define add_history(x) ((void)0) +#endif + +#ifdef HAVE_LIBREADLINE +# include <readline/readline.h> +#else /* !HAVE_LIBREADLINE */ +static char * +readline (char *prompt) +{ + 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 <jao@gnu.org> + + * de.po (Module): mike's german translation. + +2002-03-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.40. + +2002-03-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.40. + * cat-id-tbl.c: Remove file. + * stamp-cat-id: Remove file. + +2001-09-26 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-27 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-26 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-25 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-25 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-25 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-23 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-22 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-21 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-20 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-17 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-08-17 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.39. + +2001-07-23 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-23 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-23 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-23 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-18 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize <bug-gnu-utils@gnu.org> + + * Makefile.in.in: Upgrade to gettext-0.10.38. + +2001-07-16 gettextize <bug-gnu-utils@gnu.org> + + * 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 <jaortega@retemail.es> + + * 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 <scholz-micha@gmx.de>, 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 <scholz-micha@gmx.de>\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 |