From: Jason Self Date: Wed, 28 Sep 2016 22:07:06 +0000 (-0700) Subject: Importing Inform 6 compiler based on commit 25a93cf from upstream dated Sep 25 2016... X-Git-Tag: v6.35~14 X-Git-Url: https://jxself.org/git/?p=inform.git;a=commitdiff_plain;h=5154191043a9b7227ef0eee1a2b40299fc188655 Importing Inform 6 compiler based on commit 25a93cf from upstream dated Sep 25 2016. Modified to work better when the Inform standard library is in a non-standard location. Relicensed to GPL per Section 4(c)(ii) of the Artistic License 2.0. --- 5154191043a9b7227ef0eee1a2b40299fc188655 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/DebugFileFormat.txt b/DebugFileFormat.txt new file mode 100644 index 0000000..9850bbf --- /dev/null +++ b/DebugFileFormat.txt @@ -0,0 +1,401 @@ +Format of Inform 6 Debugging Information Files + +Version 1.0 + +0: Introduction + +This is a specification of the Version 1 format for the debugging information +files emitted by the Inform 6 compiler. It replaces Version 0, which is +documented in Section 12.5 of the Inform Technical Manual. + +1: Overview + +Debugging information files are written in XML and encoded in UTF-8. They +therefore begin with the following declaration: + + + +Beyond the usual requirements for well-formed XML, the file adheres to the +conventions that all numbers are written in decimal, all strings are +case-sensitive, and all excerpts from binary files are Base64-encoded. + +2: The Top Level + +The root element is given by the tag with three attributes, +the version of the debug file format being used, the name of the program that +produced the file, and that program's version. For instance, + + + ... + + +The elements from Sections 3--8 may appear in the ellipses. + +3: Story File Prefix + +The story file prefix contains a Base64 encoding of the story file's first bytes +so that a debugging tool can easily check whether the story and the debug +information file are mismatched. For example, the prefix for a Glulx story +might appear as + + + R2x1bAADAQEACqEAAAwsAAAMLAAAAQAAAAAAPAAIo2Jc + 6B2XSW5mbwABAAA2LjMyMC4zOAABMTIxMDE1wQAAMA== + + +The story file prefix is mandatory, but its length is unspecified. Version 6.33 +of the Inform compiler records 64 bytes, which seems sufficient. + +4: Story File Sections + +Story file sections partition the story file according to how the data will be +used. For the Inform 6 compiler, this partitioning is the same as the one that +the `z' flag prints. + +A record for a story file section gives a name for that section, its beginning +address (inclusive), and its end address (exclusive): + + + abbreviations table +
64
+ 128 +
+ +The names currently in use include those from Section 12.5 of the Inform +Technical Manual: + + abbreviations table + header extension (Z-code only) + alphabets table (Z-code only) + Unicode table (Z-code only) + property defaults + object tree + common properties + class numbers + individual properties (Z-code only) + global variables + array space + grammar table + actions table + parsing routines (Z-code only) + adjectives table (Z-code only) + dictionary + code area + strings area + +plus one addition for Z-code: + + abbreviations + +two additions for Glulx: + + memory layout id + string decoding table + +and three additions for both targets: + + header + identifier names + zero padding + +Names may repeat; Glulx story files, for example, sometimes have two zero +padding sections. + +A compiler that does not wish to subdivide the story file should emit one +section for the entirety and give it the name + + story + +5: Source Files + +Source files are encoded as in the example below. Each file has a unique index, +which is used by other elements when referring to source code locations; these +indices count from zero. The file's path is recorded in two forms, first as it +was given to the compiler via a command-line argument or include directive but +without any path abbreviations like `>' (the form suitable for presentation to a +human) and second after resolution to an absolute path (the form suitable for +loading the file contents). All paths are written according to the conventions +of the host OS. The language is, at present, either "Inform 6" or "Inform 7". +More languages may added in the future. + + + example.inf + /home/user/directory/example.inf + Inform 6 + + +If the source file is known to appear in the story's Blorb, its chunk number +will also be recorded: + + + example.inf + /home/user/directory/example.inf + Inform 6 + 18 + + +6: Table Entries; Grammar Lines + +Table entries are data defined by particular parts of the source code, but +without any corresponding identifiers. The element notes the +entry's type, the address where it begins (inclusive), the address where it ends +(exclusive), and the defining source code location(s), if any: + + + grammar line +
1004
+ 1030 + ... +
+ +Version 6.33 of the Inform compiler only emits tags for grammar +lines; these data are all located in the grammar table section. + +7: Named Values; Constants, Attributes, Properties, Actions, Fake Actions, + Objects, Classes, Arrays, and Routines + +Records for named values store their identifier, their value, and the source +code location(s) of their definition, if any. For instance, + + + MAX_SCORE + 40 + ... + + +would represent a named constant. Attributes, properties, actions, fake +actions, objects, arrays, and routines are also names for numbers, and differ +only in their use; they are represented in the same format under the tags +, , , , , , and +. (Moreover, unlike Version 0 of the debug information format, fake +actions are not recorded as both fake actions and actions.) + +The records for constants include some extra entries for the system constants +tabulated in Section 12.2 of the Inform Technical Manual, even though these are +not created by Constant directives. Entries for #undefed constants are also +included, but necessarily without values. + +Some records for objects will represent class objects. In that case, they will +be given with the tag rather than and include an additional +child to indicate their class number: + + + lamp + 5 + 1560 + ... + + +Records for arrays also have extra children, which record their size, their +element size, and the intended semantics for their zeroth element: + + + route + 1500 + 20 + 4 + true + ... + + +And finally, records contain an
and a element, +along with any number of the and elements, +which are described in Sections 9 and 10. The address is provided because the +identifier's value may be packed. + +Sometimes what would otherwise be a named value is in fact anonymous; unnamed +objects, embedded routines, some replaced routines, veneer properties, and the +Infix attribute are all examples. In such a case, the subelement +will carry the XML attribute + + artificial + +to indicate that the compiler is providing a sensible name of its own, which +could be presented to a human, but is not actually an identifier. For instance: + + + lantern.time_left + 1820 + 80 + ... + ... + + +Artificial identifiers may contain characters, like the full stop in +``lantern.time_left'', that would not be legal in the source language. + +8: Global Variables + +Globals are similar to named values, except that they are not interpreted as a +fixed value, but rather have an address where their value can be found. Their +records therefore contain an
tag in place of the tag, as in: + + + darkness_witnessed +
1520
+ ... +
+ +9: Local Variables + +The format for local variables mimics the format for global variables, except +that a source code location is never included, and their memory locations are +not given by address. For Z-code, locals are specified by index: + + + parameter + 1 + + +whereas for Glulx they are specified by frame offset: + + + parameter + 4 + + +If a local variable identifier is only in scope for part of a routine, it's +scope will be encoded as a beginning instruction address (inclusive) and an +ending instruction address (exclusive): + + + rulebook + 0 + 1628 + 1678 + + +Identifiers with noncontiguous scopes are recorded as one +element per contiguous region. It is possible for the same identifier to map to +different variables, so long as the corresponding scopes are disjoint. + +10: Sequence Points + +Sequence points are stored as an instruction address and the corresponding +single location in the source code: + + +
1628
+ ... +
+ +The source code location will always be exactly one position with overlapping +endpoints. + +Sequence points are defined as in Section 12.4 of the Inform Technical Manual, +but with the further stipulation that labels do not influence their source code +locations, as they did in Version 0 of the debug information format. For +instance, in code like + + say__p = 1; ParaContent(); .L_Say59; .LSayX59; + t_0 = 0; + +the sequence points are to be placed like this: + + <*> say__p = 1; <*> ParaContent(); .L_Say59; .LSayX59; + <*> t_0 = 0; + +rather than like this: + + <*> say__p = 1; <*> ParaContent(); <*> .L_Say59; .LSayX59; + t_0 = 0; + +11: Source Code Locations + +Most source code locations take the following format, which describes their +file, the line and character number where they begin (inclusive), the line and +character number where they end (exclusive), and the file positions (in bytes) +corresponding to those endpoints: + + + 0 + 1024 + 4 + 44153 + 1025 + 1 + 44186 + + +Line numbers and character numbers begin at one, but file positions count from +zero. + +In the special case where the endpoints coincide, as happens with sequence +points, the end elements may be elided: + + + 0 + 1024 + 4 + 44153 + + +At the other extreme, sometimes definitions span several source files or appear +in two different languages. The former case is dealt with by including multiple +code location elements and indexing them to indicate order: + + + + + 0 + 1024 + 4 + 44153 + 1025 + 1 + 44186 + + + + + 1 + 1 + 0 + 0 + 3 + 1 + 59 + + +The latter case is also handled with multiple elements. Note that indexing is +only used to indicated order among locations in the same language. + + + + + 2 + 12 + 0 + 308 + 12 + 112 + 420 + + + + + 0 + 1024 + 4 + 44153 + 1025 + 1 + 44186 + + +-- +This file is part of Inform. + +Inform is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation, either version 3 of the License, or (at your +option) any later version. + +Inform is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Inform. If not, see https://gnu.org/licenses/ diff --git a/arrays.c b/arrays.c new file mode 100644 index 0000000..0f1d3e5 --- /dev/null +++ b/arrays.c @@ -0,0 +1,672 @@ +/* ------------------------------------------------------------------------- */ +/* "arrays" : Parses array declarations and constructs arrays from them; */ +/* likewise global variables, which are in some ways a */ +/* simpler form of the same thing. */ +/* */ +/* Copyright (c) Graham Nelson 1993 - 2016 */ +/* */ +/* This file is part of Inform. */ +/* */ +/* Inform is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Inform is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Inform. If not, see https://gnu.org/licenses/ */ +/* */ +/* ------------------------------------------------------------------------- */ + +#include "header.h" + +/* ------------------------------------------------------------------------- */ +/* Arrays defined below: */ +/* */ +/* int dynamic_array_area[] Initial values for the bytes of */ +/* the dynamic array area */ +/* int32 global_initial_value[n] The initialised value of the nth */ +/* global variable (counting 0 - 239) */ +/* */ +/* The "dynamic array area" is the Z-machine area holding the current */ +/* values of the global variables (in 240x2 = 480 bytes) followed by any */ +/* (dynamic) arrays which may be defined. Owing to a poor choice of name */ +/* some years ago, this is also called the "static data area", which is */ +/* why the memory setting for its maximum extent is "MAX_STATIC_DATA". */ +/* */ +/* In Glulx, that 240 is changed to MAX_GLOBAL_VAR_NUMBER, and we take */ +/* correspondingly more space for the globals. This *really* ought to be */ +/* split into two segments. */ +/* ------------------------------------------------------------------------- */ +int *dynamic_array_area; /* See above */ +int32 *global_initial_value; + +int no_globals; /* Number of global variables used + by the programmer (Inform itself + uses the top seven -- but these do + not count) */ + /* In Glulx, Inform uses the bottom + ten. */ + +int dynamic_array_area_size; /* Size in bytes */ + +int no_arrays; +int32 *array_symbols; +int *array_sizes, *array_types; + +static int array_entry_size, /* 1 for byte array, 2 for word array */ + array_base; /* Offset in dynamic array area of the + array being constructed. During the + same time, dynamic_array_area_size + is the offset of the initial entry + in the array: so for "table" and + "string" arrays, these numbers are + different (by 2 and 1 bytes resp) */ + + /* In Glulx, of course, that will be + 4 instead of 2. */ + +extern void finish_array(int32 i) +{ + /* Write the array size into the 0th byte/word of the array, if it's + a "table" or "string" array */ + if (!glulx_mode) { + + if (array_base!=dynamic_array_area_size) + { if (dynamic_array_area_size-array_base==2) + { dynamic_array_area[array_base] = i/256; + dynamic_array_area[array_base+1] = i%256; + } + else + { if (i>=256) + error("A 'string' array can have at most 256 entries"); + dynamic_array_area[array_base] = i; + } + } + + } + else { + if (array_base!=dynamic_array_area_size) + { if (dynamic_array_area_size-array_base==4) + { + dynamic_array_area[array_base] = (i >> 24) & 0xFF; + dynamic_array_area[array_base+1] = (i >> 16) & 0xFF; + dynamic_array_area[array_base+2] = (i >> 8) & 0xFF; + dynamic_array_area[array_base+3] = (i) & 0xFF; + } + else + { if (i>=256) + error("A 'string' array can have at most 256 entries"); + dynamic_array_area[array_base] = i; + } + } + + } + + /* Move on the dynamic array size so that it now points to the next + available free space */ + + dynamic_array_area_size += i*array_entry_size; + +} + +extern void array_entry(int32 i, assembly_operand VAL) +{ + if (!glulx_mode) { + /* Array entry i (initial entry has i=0) is set to Z-machine value j */ + + if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA) + memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA); + + if (array_entry_size==1) + { dynamic_array_area[dynamic_array_area_size+i] = (VAL.value)%256; + + if (VAL.marker != 0) + error("Entries in byte arrays and strings must be known constants"); + + /* If the entry is too large for a byte array, issue a warning + and truncate the value */ + else + if (VAL.value >= 256) + warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255"); + } + else + { dynamic_array_area[dynamic_array_area_size + 2*i] = (VAL.value)/256; + dynamic_array_area[dynamic_array_area_size + 2*i+1] = (VAL.value)%256; + if (VAL.marker != 0) + backpatch_zmachine(VAL.marker, DYNAMIC_ARRAY_ZA, + dynamic_array_area_size + 2*i); + } + } + else { + /* Array entry i (initial entry has i=0) is set to value j */ + + if (dynamic_array_area_size+(i+1)*array_entry_size > MAX_STATIC_DATA) + memoryerror("MAX_STATIC_DATA", MAX_STATIC_DATA); + + if (array_entry_size==1) + { dynamic_array_area[dynamic_array_area_size+i] = (VAL.value) & 0xFF; + + if (VAL.marker != 0) + error("Entries in byte arrays and strings must be known constants"); + + /* If the entry is too large for a byte array, issue a warning + and truncate the value */ + else + if (VAL.value >= 256) + warning("Entry in '->', 'string' or 'buffer' array not in range 0 to 255"); + } + else if (array_entry_size==4) + { dynamic_array_area[dynamic_array_area_size + 4*i] = (VAL.value >> 24) & 0xFF; + dynamic_array_area[dynamic_array_area_size + 4*i+1] = (VAL.value >> 16) & 0xFF; + dynamic_array_area[dynamic_array_area_size + 4*i+2] = (VAL.value >> 8) & 0xFF; + dynamic_array_area[dynamic_array_area_size + 4*i+3] = (VAL.value) & 0xFF; + if (VAL.marker != 0) + backpatch_zmachine(VAL.marker, ARRAY_ZA, + dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES + 4*i); + } + else + { + error("Somehow created an array of shorts"); + } + } +} + +/* ------------------------------------------------------------------------- */ +/* Global and Array directives. */ +/* */ +/* Global | */ +/* | = */ +/* | */ +/* */ +/* Array */ +/* */ +/* where an array specification is: */ +/* */ +/* | -> | */ +/* | --> | ... */ +/* | string | [ [,] [;] ... ]; */ +/* | table */ +/* */ +/* ------------------------------------------------------------------------- */ + +extern void set_variable_value(int i, int32 v) +{ global_initial_value[i]=v; +} + +/* There are four ways to initialise arrays: */ + +#define UNSPECIFIED_AI -1 +#define NULLS_AI 0 +#define DATA_AI 1 +#define ASCII_AI 2 +#define BRACKET_AI 3 + +extern void make_global(int array_flag, int name_only) +{ + /* array_flag is TRUE for an Array directive, FALSE for a Global; + name_only is only TRUE for parsing an imported variable name, so + array_flag is always FALSE in that case. */ + + int32 i; + int array_type, data_type; + assembly_operand AO; + + int32 global_symbol; + const char *global_name; + debug_location_beginning beginning_debug_location = + get_token_location_beginning(); + + directive_keywords.enabled = FALSE; + get_next_token(); + i = token_value; + global_symbol = i; + global_name = token_text; + + if (!glulx_mode) { + if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T) + && (svals[i] >= LOWEST_SYSTEM_VAR_NUMBER)) + goto RedefinitionOfSystemVar; + } + else { + if ((token_type==SYMBOL_TT) && (stypes[i]==GLOBAL_VARIABLE_T)) + goto RedefinitionOfSystemVar; + } + + if ((token_type != SYMBOL_TT) || (!(sflags[i] & UNKNOWN_SFLAG))) + { discard_token_location(beginning_debug_location); + if (array_flag) + ebf_error("new array name", token_text); + else ebf_error("new global variable name", token_text); + panic_mode_error_recovery(); return; + } + + if ((!array_flag) && (sflags[i] & USED_SFLAG)) + error_named("Variable must be defined before use:", token_text); + + if (array_flag) + { + if (!glulx_mode) + assign_symbol(i, dynamic_array_area_size, ARRAY_T); + else + assign_symbol(i, + dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES, ARRAY_T); + if (no_arrays == MAX_ARRAYS) + memoryerror("MAX_ARRAYS", MAX_ARRAYS); + array_symbols[no_arrays] = i; + } + else + { if (!glulx_mode && no_globals==233) + { discard_token_location(beginning_debug_location); + error("All 233 global variables already declared"); + panic_mode_error_recovery(); + return; + } + if (glulx_mode && no_globals==MAX_GLOBAL_VARIABLES) + { discard_token_location(beginning_debug_location); + memoryerror("MAX_GLOBAL_VARIABLES", MAX_GLOBAL_VARIABLES); + panic_mode_error_recovery(); + return; + } + + variable_tokens[MAX_LOCAL_VARIABLES+no_globals] = i; + assign_symbol(i, MAX_LOCAL_VARIABLES+no_globals, GLOBAL_VARIABLE_T); + variable_tokens[svals[i]] = i; + + if (name_only) import_symbol(i); + else global_initial_value[no_globals++]=0; + } + + directive_keywords.enabled = TRUE; + + RedefinitionOfSystemVar: + + if (name_only) + { discard_token_location(beginning_debug_location); + return; + } + + get_next_token(); + + if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) + { if (array_flag) + { discard_token_location(beginning_debug_location); + ebf_error("array definition", token_text); + } + put_token_back(); + if (debugfile_switch && !array_flag) + { debug_file_printf(""); + debug_file_printf("%s", global_name); + debug_file_printf("
"); + write_debug_global_backpatch(svals[global_symbol]); + debug_file_printf("
"); + write_debug_locations + (get_token_location_end(beginning_debug_location)); + debug_file_printf("
"); + } + return; + } + + if (!array_flag) + { + if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP)) + { AO = parse_expression(CONSTANT_CONTEXT); + if (!glulx_mode) { + if (AO.marker != 0) + backpatch_zmachine(AO.marker, DYNAMIC_ARRAY_ZA, + 2*(no_globals-1)); + } + else { + if (AO.marker != 0) + backpatch_zmachine(AO.marker, GLOBALVAR_ZA, + 4*(no_globals-1)); + } + global_initial_value[no_globals-1] = AO.value; + if (debugfile_switch) + { debug_file_printf(""); + debug_file_printf("%s", global_name); + debug_file_printf("
"); + write_debug_global_backpatch(svals[global_symbol]); + debug_file_printf("
"); + write_debug_locations + (get_token_location_end(beginning_debug_location)); + debug_file_printf("
"); + } + return; + } + + obsolete_warning("more modern to use 'Array', not 'Global'"); + + if (!glulx_mode) { + backpatch_zmachine(ARRAY_MV, DYNAMIC_ARRAY_ZA, 2*(no_globals-1)); + global_initial_value[no_globals-1] + = dynamic_array_area_size+variables_offset; + } + else { + backpatch_zmachine(ARRAY_MV, GLOBALVAR_ZA, 4*(no_globals-1)); + global_initial_value[no_globals-1] + = dynamic_array_area_size - 4*MAX_GLOBAL_VARIABLES; + } + } + + array_type = BYTE_ARRAY; data_type = UNSPECIFIED_AI; + + if ((!array_flag) && + ((token_type==DIR_KEYWORD_TT)&&(token_value==DATA_DK))) + data_type=NULLS_AI; + else if ((!array_flag) && + ((token_type==DIR_KEYWORD_TT)&&(token_value==INITIAL_DK))) + data_type=DATA_AI; + else if ((!array_flag) && + ((token_type==DIR_KEYWORD_TT)&&(token_value==INITSTR_DK))) + data_type=ASCII_AI; + + else if ((token_type==SEP_TT)&&(token_value==ARROW_SEP)) + array_type = BYTE_ARRAY; + else if ((token_type==SEP_TT)&&(token_value==DARROW_SEP)) + array_type = WORD_ARRAY; + else if ((token_type==DIR_KEYWORD_TT)&&(token_value==STRING_DK)) + array_type = STRING_ARRAY; + else if ((token_type==DIR_KEYWORD_TT)&&(token_value==TABLE_DK)) + array_type = TABLE_ARRAY; + else if ((token_type==DIR_KEYWORD_TT)&&(token_value==BUFFER_DK)) + array_type = BUFFER_ARRAY; + else + { discard_token_location(beginning_debug_location); + if (array_flag) + ebf_error + ("'->', '-->', 'string', 'table' or 'buffer'", token_text); + else + ebf_error + ("'=', '->', '-->', 'string', 'table' or 'buffer'", token_text); + panic_mode_error_recovery(); + return; + } + + array_entry_size=1; + if ((array_type==WORD_ARRAY) || (array_type==TABLE_ARRAY)) + array_entry_size=WORDSIZE; + + get_next_token(); + if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) + { discard_token_location(beginning_debug_location); + error("No array size or initial values given"); + put_token_back(); + return; + } + + switch(data_type) + { case UNSPECIFIED_AI: + if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP)) + data_type = BRACKET_AI; + else + { data_type = NULLS_AI; + if (token_type == DQ_TT) data_type = ASCII_AI; + get_next_token(); + if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))) + data_type = DATA_AI; + put_token_back(); + put_token_back(); + } + break; + case NULLS_AI: obsolete_warning("use '->' instead of 'data'"); break; + case DATA_AI: obsolete_warning("use '->' instead of 'initial'"); break; + case ASCII_AI: obsolete_warning("use '->' instead of 'initstr'"); break; + } + + array_base = dynamic_array_area_size; + + /* Leave room to write the array size in later, if string/table array */ + + if ((array_type==STRING_ARRAY) || (array_type==TABLE_ARRAY)) + dynamic_array_area_size += array_entry_size; + if (array_type==BUFFER_ARRAY) + dynamic_array_area_size += WORDSIZE; + array_types[no_arrays] = array_type; + + switch(data_type) + { + case NULLS_AI: + + AO = parse_expression(CONSTANT_CONTEXT); + + CalculatedArraySize: + + if (module_switch && (AO.marker != 0)) + { error("Array sizes must be known now, not externally defined"); + break; + } + + if (!glulx_mode) { + if ((AO.value <= 0) || (AO.value >= 32768)) + { error("An array must have between 1 and 32767 entries"); + AO.value = 1; + } + } + else { + if (AO.value <= 0 || (AO.value & 0x80000000)) + { error("An array may not have 0 or fewer entries"); + AO.value = 1; + } + } + + { for (i=0; i= 256)) + { + error("Unicode characters beyond Latin-1 cannot be used in a byte array"); + } + else + { + chars.value = unicode; + } + } + else /* Z-code */ + { + zscii = unicode_to_zscii(unicode); + if ((zscii != 5) && (zscii < 0x100)) chars.value = zscii; + else + { unicode_char_error("Character can only be used if declared in \ +advance as part of 'Zcharacter table':", unicode); + chars.value = '?'; + } + } + chars.marker = 0; + set_constant_ot(&chars); + array_entry(i, chars); + } + } + break; + + case BRACKET_AI: + + /* In this case the array is initialised to the sequence of + constant values given over a whole range of compiler-lines, + between square brackets [ and ] */ + + i = 0; + while (TRUE) + { get_next_token(); + if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)) + continue; + if ((token_type == SEP_TT) && (token_value == CLOSE_SQUARE_SEP)) + break; + if ((token_type == SEP_TT) && (token_value == OPEN_SQUARE_SEP)) + { /* Minimal error recovery: we assume that a ] has + been missed, and the programmer is now starting + a new routine */ + + ebf_error("']'", token_text); + put_token_back(); break; + } + put_token_back(); + array_entry(i, parse_expression(ARRAY_CONTEXT)); + i++; + } + } + + finish_array(i); + + if (debugfile_switch) + { debug_file_printf(""); + debug_file_printf("%s", global_name); + debug_file_printf(""); + write_debug_array_backpatch(svals[global_symbol]); + debug_file_printf(""); + debug_file_printf + ("%d", + dynamic_array_area_size - array_base); + debug_file_printf + ("%d", + array_entry_size); + debug_file_printf + ("%s", + (array_type == STRING_ARRAY || array_type == TABLE_ARRAY) ? + "true" : "false"); + get_next_token(); + write_debug_locations(get_token_location_end(beginning_debug_location)); + put_token_back(); + debug_file_printf(""); + } + + if ((array_type==BYTE_ARRAY) || (array_type==WORD_ARRAY)) i--; + if (array_type==BUFFER_ARRAY) i+=WORDSIZE-1; + array_sizes[no_arrays++] = i; +} + +extern int32 begin_table_array(void) +{ + /* The "box" statement needs to be able to construct (static) table + arrays of strings like this */ + + array_base = dynamic_array_area_size; + array_entry_size = WORDSIZE; + + /* Leave room to write the array size in later */ + + dynamic_array_area_size += array_entry_size; + + if (!glulx_mode) + return array_base; + else + return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES; +} + +extern int32 begin_word_array(void) +{ + /* The "random(a, b, ...)" function needs to be able to construct + (static) word arrays like this */ + + array_base = dynamic_array_area_size; + array_entry_size = WORDSIZE; + + if (!glulx_mode) + return array_base; + else + return array_base - WORDSIZE * MAX_GLOBAL_VARIABLES; +} + +/* ========================================================================= */ +/* Data structure management routines */ +/* ------------------------------------------------------------------------- */ + +extern void init_arrays_vars(void) +{ dynamic_array_area = NULL; + global_initial_value = NULL; + array_sizes = NULL; array_symbols = NULL; array_types = NULL; +} + +extern void arrays_begin_pass(void) +{ no_arrays = 0; + if (!glulx_mode) + no_globals=0; + else + no_globals=11; + dynamic_array_area_size = WORDSIZE * MAX_GLOBAL_VARIABLES; +} + +extern void arrays_allocate_arrays(void) +{ dynamic_array_area = my_calloc(sizeof(int), MAX_STATIC_DATA, + "static data"); + array_sizes = my_calloc(sizeof(int), MAX_ARRAYS, "array sizes"); + array_types = my_calloc(sizeof(int), MAX_ARRAYS, "array types"); + array_symbols = my_calloc(sizeof(int32), MAX_ARRAYS, "array symbols"); + global_initial_value = my_calloc(sizeof(int32), MAX_GLOBAL_VARIABLES, + "global values"); +} + +extern void arrays_free_arrays(void) +{ my_free(&dynamic_array_area, "static data"); + my_free(&global_initial_value, "global values"); + my_free(&array_sizes, "array sizes"); + my_free(&array_types, "array sizes"); + my_free(&array_symbols, "array sizes"); +} + +/* ========================================================================= */ diff --git a/asm.c b/asm.c new file mode 100644 index 0000000..a144939 --- /dev/null +++ b/asm.c @@ -0,0 +1,3189 @@ +/* ------------------------------------------------------------------------- */ +/* "asm" : The Inform assembler */ +/* */ +/* Copyright (c) Graham Nelson 1993 - 2016 */ +/* */ +/* This file is part of Inform. */ +/* */ +/* Inform is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Inform is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Inform. If not, see https://gnu.org/licenses/ */ +/* */ +/* ------------------------------------------------------------------------- */ + +#include "header.h" + +uchar *zcode_holding_area; /* Area holding code yet to be transferred + to either zcode_area or temp file no 1 */ +uchar *zcode_markers; /* Bytes holding marker values for this + code */ +static int zcode_ha_size; /* Number of bytes in holding area */ + +memory_block zcode_area; /* Block to hold assembled code (if + temporary files are not being used) */ + +int32 zmachine_pc; /* PC position of assembly (byte offset + from start of Z-code area) */ + +int32 no_instructions; /* Number of instructions assembled */ +int execution_never_reaches_here, /* TRUE if the current PC value in the + code area cannot be reached: e.g. if + the previous instruction was a "quit" + opcode and no label is set to here */ + next_label, /* Used to count the labels created all + over Inform in current routine, from 0 */ + next_sequence_point; /* Likewise, for sequence points */ +int no_sequence_points; /* Kept for statistics purposes only */ + +static int label_moved_error_already_given; + /* When one label has moved, all subsequent + ones probably have too, and this flag + suppresses the runaway chain of error + messages which would otherwise result */ + +int sequence_point_follows; /* Will the next instruction assembled */ + /* be at a sequence point in the routine? */ + +int uses_unicode_features; /* Makes use of Glulx Unicode (3.0) + features? */ +int uses_memheap_features; /* Makes use of Glulx mem/heap (3.1) + features? */ +int uses_acceleration_features; /* Makes use of Glulx acceleration (3.1.1) + features? */ +int uses_float_features; /* Makes use of Glulx floating-point (3.1.2) + features? */ + +debug_location statement_debug_location; + /* Location of current statement */ + + +int32 *variable_tokens; /* The allocated size is + (MAX_LOCAL_VARIABLES + + MAX_GLOBAL_VARIABLES). The entries + MAX_LOCAL_VARIABLES and up give the + symbol table index for the names of + the global variables */ +int *variable_usage; /* TRUE if referred to, FALSE otherwise */ + +assembly_instruction AI; /* A structure used to hold the full + specification of a single Z-code + instruction: effectively this is the + input to the routine + assemble_instruction() */ + +static char opcode_syntax_string[128]; /* Text buffer holding the correct + syntax for an opcode: used to produce + helpful assembler error messages */ + +static int routine_symbol; /* The symbol index of the routine currently + being compiled */ +static char *routine_name; /* The name of the routine currently being + compiled */ +static int routine_locals; /* The number of local variables used by + the routine currently being compiled */ + +static int32 routine_start_pc; + +int32 *named_routine_symbols; + +static void transfer_routine_z(void); +static void transfer_routine_g(void); + +/* ------------------------------------------------------------------------- */ +/* Label data */ +/* ------------------------------------------------------------------------- */ + +static int first_label, last_label; +static int32 *label_offsets; /* Double-linked list of label offsets */ +static int *label_next, /* (i.e. zmachine_pc values) in PC order */ + *label_prev; +static int32 *label_symbols; /* Symbol numbers if defined in source */ + +static int *sequence_point_labels; + /* Label numbers for each */ +static debug_location *sequence_point_locations; + /* Source code references for each */ + /* (used for making debugging file) */ + +static void set_label_offset(int label, int32 offset) +{ + if (label >= MAX_LABELS) memoryerror("MAX_LABELS", MAX_LABELS); + + label_offsets[label] = offset; + if (last_label == -1) + { label_prev[label] = -1; + first_label = label; + } + else + { label_prev[label] = last_label; + label_next[last_label] = label; + } + last_label = label; + label_next[label] = -1; + label_symbols[label] = -1; +} + +/* ------------------------------------------------------------------------- */ +/* Useful tool for building operands */ +/* ------------------------------------------------------------------------- */ + +extern void set_constant_ot(assembly_operand *AO) +{ + if (!glulx_mode) { + if (AO->value >= 0 && AO->value <= 255) + AO->type = SHORT_CONSTANT_OT; + else + AO->type = LONG_CONSTANT_OT; + } + else { + if (AO->value == 0) + AO->type = ZEROCONSTANT_OT; + else if (AO->value >= -0x80 && AO->value < 0x80) + AO->type = BYTECONSTANT_OT; + else if (AO->value >= -0x8000 && AO->value < 0x8000) + AO->type = HALFCONSTANT_OT; + else + AO->type = CONSTANT_OT; + } +} + +extern int is_constant_ot(int otval) +{ + if (!glulx_mode) { + return ((otval == LONG_CONSTANT_OT) + || (otval == SHORT_CONSTANT_OT)); + } + else { + return ((otval == CONSTANT_OT) + || (otval == HALFCONSTANT_OT) + || (otval == BYTECONSTANT_OT) + || (otval == ZEROCONSTANT_OT)); + } +} + +extern int is_variable_ot(int otval) +{ + if (!glulx_mode) { + return (otval == VARIABLE_OT); + } + else { + return ((otval == LOCALVAR_OT) + || (otval == GLOBALVAR_OT)); + } +} + +/* ------------------------------------------------------------------------- */ +/* Used in printing assembly traces */ +/* ------------------------------------------------------------------------- */ + +extern char *variable_name(int32 i) +{ + if (i==0) return("sp"); + if (i= 256 && i < 286) + { if (i - 256 < NUMBER_SYSTEM_FUNCTIONS) return system_functions.keywords[i - 256]; + return ""; + } + } + else { + switch (i - MAX_LOCAL_VARIABLES) { + case 0: return "temp_global"; + case 1: return "temp__global2"; + case 2: return "temp__global3"; + case 3: return "temp__global4"; + case 4: return "self"; + case 5: return "sender"; + case 6: return "sw__var"; + case 7: return "sys__glob0"; + case 8: return "sys__glob1"; + case 9: return "sys__glob2"; + case 10: return "sys_statusline_flag"; + } + } + + return ((char *) symbs[variable_tokens[i]]); +} + +static void print_operand_z(assembly_operand o) +{ switch(o.type) + { case EXPRESSION_OT: printf("expr_"); break; + case LONG_CONSTANT_OT: printf("long_"); break; + case SHORT_CONSTANT_OT: printf("short_"); break; + case VARIABLE_OT: + if (o.value==0) { printf("sp"); return; } + printf("%s", variable_name(o.value)); return; + case OMITTED_OT: printf(""); return; + } + printf("%d", o.value); +} + +static void print_operand_g(assembly_operand o) +{ + switch (o.type) { + case EXPRESSION_OT: printf("expr_"); break; + case CONSTANT_OT: printf("long_"); break; + case HALFCONSTANT_OT: printf("short_"); break; + case BYTECONSTANT_OT: printf("byte_"); break; + case ZEROCONSTANT_OT: printf("zero_"); return; + case DEREFERENCE_OT: printf("*"); break; + case GLOBALVAR_OT: + printf("%s (global_%d)", variable_name(o.value), o.value); + return; + case LOCALVAR_OT: + if (o.value == 0) + printf("stackptr"); + else + printf("%s (local_%d)", variable_name(o.value), o.value-1); + return; + case SYSFUN_OT: + if (o.value >= 0 && o.value < NUMBER_SYSTEM_FUNCTIONS) + printf("%s", system_functions.keywords[o.value]); + else + printf(""); + return; + case OMITTED_OT: printf(""); return; + default: printf("???_"); break; + } + printf("%d", o.value); +} + +extern void print_operand(assembly_operand o) +{ + if (!glulx_mode) + print_operand_z(o); + else + print_operand_g(o); +} + +/* ------------------------------------------------------------------------- */ +/* Writing bytes to the code area */ +/* ------------------------------------------------------------------------- */ + +static void byteout(int32 i, int mv) +{ if (zcode_ha_size >= MAX_ZCODE_SIZE) + memoryerror("MAX_ZCODE_SIZE",MAX_ZCODE_SIZE); + zcode_markers[zcode_ha_size] = (uchar) mv; + zcode_holding_area[zcode_ha_size++] = (uchar) i; + zmachine_pc++; +} + +/* ------------------------------------------------------------------------- */ +/* A database of the 115 canonical Infocom opcodes in Versions 3 to 6 */ +/* And of the however-many-there-are Glulx opcode */ +/* ------------------------------------------------------------------------- */ + +typedef struct opcodez +{ uchar *name; /* Lower case standard name */ + int version1; /* Valid from this version number... */ + int version2; /* ...until this one (or forever if this is 0) */ + int extension; /* In later versions, see this line in extension table: + if -1, the opcode is illegal in later versions */ + int code; /* Opcode number within its operand-number block */ + int flags; /* Flags (see below) */ + int op_rules; /* Any unusual operand rule applying (see below) */ + int flags2_set; /* If not zero, set this bit in Flags 2 in the header + of any game using the opcode */ + int no; /* Number of operands (see below) */ +} opcodez; + +typedef struct opcodeg +{ uchar *name; /* Lower case standard name */ + int32 code; /* Opcode number */ + int flags; /* Flags (see below) */ + int op_rules; /* Any unusual operand rule applying (see below) */ + int no; /* Number of operands */ +} opcodeg; + + /* Flags which can be set */ + +#define St 1 /* Store */ +#define Br 2 /* Branch */ +#define Rf 4 /* "Return flag": execution never continues after this + opcode (e.g., is a return or unconditional jump) */ +#define St2 8 /* Store2 (second-to-last operand is store (Glulx)) */ + + /* Codes for any unusual operand assembly rules */ + + /* Z-code: */ + +#define VARIAB 1 /* First operand expected to be a variable name and + assembled to a short constant: the variable number */ +#define TEXT 2 /* One text operand, to be Z-encoded into the program */ +#define LABEL 3 /* One operand, a label, given as long constant offset */ +#define CALL 4 /* First operand is name of a routine, to be assembled + as long constant (the routine's packed address): + as if the name were prefixed by #r$ */ + + /* Glulx: (bit flags for Glulx VM features) */ + +#define GOP_Unicode 1 /* uses_unicode_features */ +#define GOP_MemHeap 2 /* uses_memheap_features */ +#define GOP_Acceleration 4 /* uses_acceleration_features */ +#define GOP_Float 8 /* uses_float_features */ + + /* Codes for the number of operands */ + +#define TWO 1 /* 2 (with certain types of operand, compiled as VAR) */ +#define VAR 2 /* 0 to 4 */ +#define VAR_LONG 3 /* 0 to 8 */ +#define ONE 4 /* 1 */ +#define ZERO 5 /* 0 */ +#define EXT 6 /* Extended opcode set VAR: 0 to 4 */ +#define EXT_LONG 7 /* Extended: 0 to 8 (not used by the canonical opcodes) */ + +static opcodez opcodes_table_z[] = +{ + /* Opcodes introduced in Version 3 */ + +/* 0 */ { (uchar *) "je", 3, 0, -1, 0x01, Br, 0, 0, TWO }, +/* 1 */ { (uchar *) "jl", 3, 0, -1, 0x02, Br, 0, 0, TWO }, +/* 2 */ { (uchar *) "jg", 3, 0, -1, 0x03, Br, 0, 0, TWO }, +/* 3 */ { (uchar *) "dec_chk", 3, 0, -1, 0x04, Br, VARIAB, 0, TWO }, +/* 4 */ { (uchar *) "inc_chk", 3, 0, -1, 0x05, Br, VARIAB, 0, TWO }, +/* 5 */ { (uchar *) "jin", 3, 0, -1, 0x06, Br, 0, 0, TWO }, +/* 6 */ { (uchar *) "test", 3, 0, -1, 0x07, Br, 0, 0, TWO }, +/* 7 */ { (uchar *) "or", 3, 0, -1, 0x08, St, 0, 0, TWO }, +/* 8 */ { (uchar *) "and", 3, 0, -1, 0x09, St, 0, 0, TWO }, +/* 9 */ { (uchar *) "test_attr", 3, 0, -1, 0x0A, Br, 0, 0, TWO }, +/* 10 */ {(uchar *) "set_attr", 3, 0, -1, 0x0B, 0, 0, 0, TWO }, +/* 11 */ {(uchar *) "clear_attr", 3, 0, -1, 0x0C, 0, 0, 0, TWO }, +/* 12 */ {(uchar *) "store", 3, 0, -1, 0x0D, 0, VARIAB, 0, TWO }, +/* 13 */ {(uchar *) "insert_obj", 3, 0, -1, 0x0E, 0, 0, 0, TWO }, +/* 14 */ {(uchar *) "loadw", 3, 0, -1, 0x0F, St, 0, 0, TWO }, +/* 15 */ {(uchar *) "loadb", 3, 0, -1, 0x10, St, 0, 0, TWO }, +/* 16 */ {(uchar *) "get_prop", 3, 0, -1, 0x11, St, 0, 0, TWO }, +/* 17 */ {(uchar *) "get_prop_addr", 3, 0, -1, 0x12, St, 0, 0, TWO }, +/* 18 */ {(uchar *) "get_next_prop", 3, 0, -1, 0x13, St, 0, 0, TWO }, +/* 19 */ {(uchar *) "add", 3, 0, -1, 0x14, St, 0, 0, TWO }, +/* 20 */ {(uchar *) "sub", 3, 0, -1, 0x15, St, 0, 0, TWO }, +/* 21 */ {(uchar *) "mul", 3, 0, -1, 0x16, St, 0, 0, TWO }, +/* 22 */ {(uchar *) "div", 3, 0, -1, 0x17, St, 0, 0, TWO }, +/* 23 */ {(uchar *) "mod", 3, 0, -1, 0x18, St, 0, 0, TWO }, +/* 24 */ {(uchar *) "call", 3, 0, -1, 0x20, St, CALL, 0, VAR }, +/* 25 */ {(uchar *) "storew", 3, 0, -1, 0x21, 0, 0, 0, VAR }, +/* 26 */ {(uchar *) "storeb", 3, 0, -1, 0x22, 0, 0, 0, VAR }, +/* 27 */ {(uchar *) "put_prop", 3, 0, -1, 0x23, 0, 0, 0, VAR }, + /* This is the version of "read" called "sread" internally: */ +/* 28 */ {(uchar *) "read", 3, 0, -1, 0x24, 0, 0, 0, VAR }, +/* 29 */ {(uchar *) "print_char", 3, 0, -1, 0x25, 0, 0, 0, VAR }, +/* 30 */ {(uchar *) "print_num", 3, 0, -1, 0x26, 0, 0, 0, VAR }, +/* 31 */ {(uchar *) "random", 3, 0, -1, 0x27, St, 0, 0, VAR }, +/* 32 */ {(uchar *) "push", 3, 0, -1, 0x28, 0, 0, 0, VAR }, +/* 33 */ {(uchar *) "pull", 3, 5, 6, 0x29, 0, VARIAB, 0, VAR }, +/* 34 */ {(uchar *) "split_window", 3, 0, -1, 0x2A, 0, 0, 0, VAR }, +/* 35 */ {(uchar *) "set_window", 3, 0, -1, 0x2B, 0, 0, 0, VAR }, +/* 36 */ {(uchar *) "output_stream", 3, 0, -1, 0x33, 0, 0, 0, VAR }, +/* 37 */ {(uchar *) "input_stream", 3, 0, -1, 0x34, 0, 0, 0, VAR }, +/* 38 */ {(uchar *) "sound_effect", 3, 0, -1, 0x35, 0, 0, 7, VAR }, +/* 39 */ {(uchar *) "jz", 3, 0, -1, 0x00, Br, 0, 0, ONE }, +/* 40 */ {(uchar *) "get_sibling", 3, 0, -1, 0x01, St+Br, 0, 0, ONE }, +/* 41 */ {(uchar *) "get_child", 3, 0, -1, 0x02, St+Br, 0, 0, ONE }, +/* 42 */ {(uchar *) "get_parent", 3, 0, -1, 0x03, St, 0, 0, ONE }, +/* 43 */ {(uchar *) "get_prop_len", 3, 0, -1, 0x04, St, 0, 0, ONE }, +/* 44 */ {(uchar *) "inc", 3, 0, -1, 0x05, 0, VARIAB, 0, ONE }, +/* 45 */ {(uchar *) "dec", 3, 0, -1, 0x06, 0, VARIAB, 0, ONE }, +/* 46 */ {(uchar *) "print_addr", 3, 0, -1, 0x07, 0, 0, 0, ONE }, +/* 47 */ {(uchar *) "remove_obj", 3, 0, -1, 0x09, 0, 0, 0, ONE }, +/* 48 */ {(uchar *) "print_obj", 3, 0, -1, 0x0A, 0, 0, 0, ONE }, +/* 49 */ {(uchar *) "ret", 3, 0, -1, 0x0B, Rf, 0, 0, ONE }, +/* 50 */ {(uchar *) "jump", 3, 0, -1, 0x0C, Rf, LABEL, 0, ONE }, +/* 51 */ {(uchar *) "print_paddr", 3, 0, -1, 0x0D, 0, 0, 0, ONE }, +/* 52 */ {(uchar *) "load", 3, 0, -1, 0x0E, St, VARIAB, 0, ONE }, +/* 53 */ {(uchar *) "not", 3, 3, 0, 0x0F, St, 0, 0, ONE }, +/* 54 */ {(uchar *) "rtrue", 3, 0, -1, 0x00, Rf, 0, 0,ZERO }, +/* 55 */ {(uchar *) "rfalse", 3, 0, -1, 0x01, Rf, 0, 0,ZERO }, +/* 56 */ {(uchar *) "print", 3, 0, -1, 0x02, 0, TEXT, 0,ZERO }, +/* 57 */ {(uchar *) "print_ret", 3, 0, -1, 0x03, Rf, TEXT, 0,ZERO }, +/* 58 */ {(uchar *) "nop", 3, 0, -1, 0x04, 0, 0, 0,ZERO }, +/* 59 */ {(uchar *) "save", 3, 3, 1, 0x05, Br, 0, 0,ZERO }, +/* 60 */ {(uchar *) "restore", 3, 3, 2, 0x06, Br, 0, 0,ZERO }, +/* 61 */ {(uchar *) "restart", 3, 0, -1, 0x07, 0, 0, 0,ZERO }, +/* 62 */ {(uchar *) "ret_popped", 3, 0, -1, 0x08, Rf, 0, 0,ZERO }, +/* 63 */ {(uchar *) "pop", 3, 4, -1, 0x09, 0, 0, 0,ZERO }, +/* 64 */ {(uchar *) "quit", 3, 0, -1, 0x0A, Rf, 0, 0,ZERO }, +/* 65 */ {(uchar *) "new_line", 3, 0, -1, 0x0B, 0, 0, 0,ZERO }, +/* 66 */ {(uchar *) "show_status", 3, 3, -1, 0x0C, 0, 0, 0,ZERO }, +/* 67 */ {(uchar *) "verify", 3, 0, -1, 0x0D, Br, 0, 0,ZERO }, + + /* Opcodes introduced in Version 4 */ + +/* 68 */ {(uchar *) "call_2s", 4, 0, -1, 0x19, St, CALL, 0, TWO }, +/* 69 */ {(uchar *) "call_vs", 4, 0, -1, 0x20, St, CALL, 0, VAR }, + /* This is the version of "read" called "aread" internally: */ +/* 70 */ {(uchar *) "read", 4, 0, -1, 0x24, St, 0, 0, VAR }, +/* 71 */ {(uchar *) "call_vs2", 4, 0, -1, 0x2C, St, CALL, 0, + VAR_LONG }, +/* 72 */ {(uchar *) "erase_window", 4, 0, -1, 0x2D, 0, 0, 0, VAR }, +/* 73 */ {(uchar *) "erase_line", 4, 0, -1, 0x2E, 0, 0, 0, VAR }, +/* 74 */ {(uchar *) "set_cursor", 4, 0, -1, 0x2F, 0, 0, 0, VAR }, +/* 75 */ {(uchar *) "get_cursor", 4, 0, -1, 0x30, 0, 0, 0, VAR }, +/* 76 */ {(uchar *) "set_text_style", 4, 0, -1, 0x31, 0, 0, 0, VAR }, +/* 77 */ {(uchar *) "buffer_mode", 4, 0, -1, 0x32, 0, 0, 0, VAR }, +/* 78 */ {(uchar *) "read_char", 4, 0, -1, 0x36, St, 0, 0, VAR }, +/* 79 */ {(uchar *) "scan_table", 4, 0, -1, 0x37, St+Br, 0, 0, VAR }, +/* 80 */ {(uchar *) "call_1s", 4, 0, -1, 0x08, St, CALL, 0, ONE }, + + /* Opcodes introduced in Version 5 */ + +/* 81 */ {(uchar *) "call_2n", 5, 0, -1, 0x1a, 0, CALL, 0, TWO }, +/* 82 */ {(uchar *) "set_colour", 5, 0, -1, 0x1b, 0, 0, 6, TWO }, +/* 83 */ {(uchar *) "throw", 5, 0, -1, 0x1c, 0, 0, 0, TWO }, +/* 84 */ {(uchar *) "call_vn", 5, 0, -1, 0x39, 0, CALL, 0, VAR }, +/* 85 */ {(uchar *) "call_vn2", 5, 0, -1, 0x3a, 0, CALL, 0, + VAR_LONG }, +/* 86 */ {(uchar *) "tokenise", 5, 0, -1, 0x3b, 0, 0, 0, VAR }, +/* 87 */ {(uchar *) "encode_text", 5, 0, -1, 0x3c, 0, 0, 0, VAR }, +/* 88 */ {(uchar *) "copy_table", 5, 0, -1, 0x3d, 0, 0, 0, VAR }, +/* 89 */ {(uchar *) "print_table", 5, 0, -1, 0x3e, 0, 0, 0, VAR }, +/* 90 */ {(uchar *) "check_arg_count", 5, 0, -1, 0x3f, Br, 0, 0, VAR }, +/* 91 */ {(uchar *) "call_1n", 5, 0, -1, 0x0F, 0, CALL, 0, ONE }, +/* 92 */ {(uchar *) "catch", 5, 0, -1, 0x09, St, 0, 0, ZERO }, +/* 93 */ {(uchar *) "piracy", 5, 0, -1, 0x0F, Br, 0, 0, ZERO }, +/* 94 */ {(uchar *) "log_shift", 5, 0, -1, 0x02, St, 0, 0, EXT }, +/* 95 */ {(uchar *) "art_shift", 5, 0, -1, 0x03, St, 0, 0, EXT }, +/* 96 */ {(uchar *) "set_font", 5, 0, -1, 0x04, St, 0, 0, EXT }, +/* 97 */ {(uchar *) "save_undo", 5, 0, -1, 0x09, St, 0, 4, EXT }, +/* 98 */ {(uchar *) "restore_undo", 5, 0, -1, 0x0A, St, 0, 4, EXT }, + + /* Opcodes introduced in Version 6 */ + +/* 99 */ { (uchar *) "draw_picture", 6, 6, -1, 0x05, 0, 0, 3, EXT }, +/* 100 */ { (uchar *) "picture_data", 6, 6, -1, 0x06, Br, 0, 3, EXT }, +/* 101 */ { (uchar *) "erase_picture", 6, 6, -1, 0x07, 0, 0, 3, EXT }, +/* 102 */ { (uchar *) "set_margins", 6, 6, -1, 0x08, 0, 0, 0, EXT }, +/* 103 */ { (uchar *) "move_window", 6, 6, -1, 0x10, 0, 0, 0, EXT }, +/* 104 */ { (uchar *) "window_size", 6, 6, -1, 0x11, 0, 0, 0, EXT }, +/* 105 */ { (uchar *) "window_style", 6, 6, -1, 0x12, 0, 0, 0, EXT }, +/* 106 */ { (uchar *) "get_wind_prop", 6, 6, -1, 0x13, St, 0, 0, EXT }, +/* 107 */ { (uchar *) "scroll_window", 6, 6, -1, 0x14, 0, 0, 0, EXT }, +/* 108 */ { (uchar *) "pop_stack", 6, 6, -1, 0x15, 0, 0, 0, EXT }, +/* 109 */ { (uchar *) "read_mouse", 6, 6, -1, 0x16, 0, 0, 5, EXT }, +/* 110 */ { (uchar *) "mouse_window", 6, 6, -1, 0x17, 0, 0, 5, EXT }, +/* 111 */ { (uchar *) "push_stack", 6, 6, -1, 0x18, Br, 0, 0, EXT }, +/* 112 */ { (uchar *) "put_wind_prop", 6, 6, -1, 0x19, 0, 0, 0, EXT }, +/* 113 */ { (uchar *) "print_form", 6, 6, -1, 0x1a, 0, 0, 0, EXT }, +/* 114 */ { (uchar *) "make_menu", 6, 6, -1, 0x1b, Br, 0, 8, EXT }, +/* 115 */ { (uchar *) "picture_table", 6, 6, -1, 0x1c, 0, 0, 3, EXT }, + + /* Opcodes introduced in Z-Machine Specification Standard 1.0 */ + +/* 116 */ { (uchar *) "print_unicode", 5, 0, -1, 0x0b, 0, 0, 0, EXT }, +/* 117 */ { (uchar *) "check_unicode", 5, 0, -1, 0x0c, St, 0, 0, EXT } +}; + + /* Subsequent forms for opcodes whose meaning changes with version */ + +static opcodez extension_table_z[] = +{ +/* 0 */ { (uchar *) "not", 4, 4, 3, 0x0F, St, 0, 0, ONE }, +/* 1 */ { (uchar *) "save", 4, 4, 4, 0x05, St, 0, 0,ZERO }, +/* 2 */ { (uchar *) "restore", 4, 4, 5, 0x06, St, 0, 0,ZERO }, +/* 3 */ { (uchar *) "not", 5, 0, -1, 0x38, St, 0, 0, VAR }, +/* 4 */ { (uchar *) "save", 5, 0, -1, 0x00, St, 0, 0, EXT }, +/* 5 */ { (uchar *) "restore", 5, 0, -1, 0x01, St, 0, 0, EXT }, +/* 6 */ { (uchar *) "pull", 6, 6, -1, 0x29, St, 0, 0, VAR } +}; + +static opcodez invalid_opcode_z = + { (uchar *) "invalid", 0, 0, -1, 0xff, 0, 0, 0, ZERO}; + +static opcodez custom_opcode_z; + +/* Note that this table assumes that all opcodes have at most two + branch-label or store operands, and that if they exist, they are the + last operands. Glulx does not actually guarantee this. But it is + true for all opcodes in the current Glulx spec, so we will assume + it for now. + + Also note that Inform can only compile branches to constant offsets, + even though the Glulx machine can handle stack or memory-loaded + operands in a branch instruction. +*/ + +static opcodeg opcodes_table_g[] = { + { (uchar *) "nop", 0x00, 0, 0, 0 }, + { (uchar *) "add", 0x10, St, 0, 3 }, + { (uchar *) "sub", 0x11, St, 0, 3 }, + { (uchar *) "mul", 0x12, St, 0, 3 }, + { (uchar *) "div", 0x13, St, 0, 3 }, + { (uchar *) "mod", 0x14, St, 0, 3 }, + { (uchar *) "neg", 0x15, St, 0, 2 }, + { (uchar *) "bitand", 0x18, St, 0, 3 }, + { (uchar *) "bitor", 0x19, St, 0, 3 }, + { (uchar *) "bitxor", 0x1A, St, 0, 3 }, + { (uchar *) "bitnot", 0x1B, St, 0, 2 }, + { (uchar *) "shiftl", 0x1C, St, 0, 3 }, + { (uchar *) "sshiftr", 0x1D, St, 0, 3 }, + { (uchar *) "ushiftr", 0x1E, St, 0, 3 }, + { (uchar *) "jump", 0x20, Br|Rf, 0, 1 }, + { (uchar *) "jz", 0x22, Br, 0, 2 }, + { (uchar *) "jnz", 0x23, Br, 0, 2 }, + { (uchar *) "jeq", 0x24, Br, 0, 3 }, + { (uchar *) "jne", 0x25, Br, 0, 3 }, + { (uchar *) "jlt", 0x26, Br, 0, 3 }, + { (uchar *) "jge", 0x27, Br, 0, 3 }, + { (uchar *) "jgt", 0x28, Br, 0, 3 }, + { (uchar *) "jle", 0x29, Br, 0, 3 }, + { (uchar *) "jltu", 0x2A, Br, 0, 3 }, + { (uchar *) "jgeu", 0x2B, Br, 0, 3 }, + { (uchar *) "jgtu", 0x2C, Br, 0, 3 }, + { (uchar *) "jleu", 0x2D, Br, 0, 3 }, + { (uchar *) "call", 0x30, St, 0, 3 }, + { (uchar *) "return", 0x31, Rf, 0, 1 }, + { (uchar *) "catch", 0x32, Br|St, 0, 2 }, + { (uchar *) "throw", 0x33, Rf, 0, 2 }, + { (uchar *) "tailcall", 0x34, Rf, 0, 2 }, + { (uchar *) "copy", 0x40, St, 0, 2 }, + { (uchar *) "copys", 0x41, St, 0, 2 }, + { (uchar *) "copyb", 0x42, St, 0, 2 }, + { (uchar *) "sexs", 0x44, St, 0, 2 }, + { (uchar *) "sexb", 0x45, St, 0, 2 }, + { (uchar *) "aload", 0x48, St, 0, 3 }, + { (uchar *) "aloads", 0x49, St, 0, 3 }, + { (uchar *) "aloadb", 0x4A, St, 0, 3 }, + { (uchar *) "aloadbit", 0x4B, St, 0, 3 }, + { (uchar *) "astore", 0x4C, 0, 0, 3 }, + { (uchar *) "astores", 0x4D, 0, 0, 3 }, + { (uchar *) "astoreb", 0x4E, 0, 0, 3 }, + { (uchar *) "astorebit", 0x4F, 0, 0, 3 }, + { (uchar *) "stkcount", 0x50, St, 0, 1 }, + { (uchar *) "stkpeek", 0x51, St, 0, 2 }, + { (uchar *) "stkswap", 0x52, 0, 0, 0 }, + { (uchar *) "stkroll", 0x53, 0, 0, 2 }, + { (uchar *) "stkcopy", 0x54, 0, 0, 1 }, + { (uchar *) "streamchar", 0x70, 0, 0, 1 }, + { (uchar *) "streamnum", 0x71, 0, 0, 1 }, + { (uchar *) "streamstr", 0x72, 0, 0, 1 }, + { (uchar *) "gestalt", 0x0100, St, 0, 3 }, + { (uchar *) "debugtrap", 0x0101, 0, 0, 1 }, + { (uchar *) "getmemsize", 0x0102, St, 0, 1 }, + { (uchar *) "setmemsize", 0x0103, St, 0, 2 }, + { (uchar *) "jumpabs", 0x0104, Rf, 0, 1 }, + { (uchar *) "random", 0x0110, St, 0, 2 }, + { (uchar *) "setrandom", 0x0111, 0, 0, 1 }, + { (uchar *) "quit", 0x0120, Rf, 0, 0 }, + { (uchar *) "verify", 0x0121, St, 0, 1 }, + { (uchar *) "restart", 0x0122, 0, 0, 0 }, + { (uchar *) "save", 0x0123, St, 0, 2 }, + { (uchar *) "restore", 0x0124, St, 0, 2 }, + { (uchar *) "saveundo", 0x0125, St, 0, 1 }, + { (uchar *) "restoreundo", 0x0126, St, 0, 1 }, + { (uchar *) "protect", 0x0127, 0, 0, 2 }, + { (uchar *) "glk", 0x0130, St, 0, 3 }, + { (uchar *) "getstringtbl", 0x0140, St, 0, 1 }, + { (uchar *) "setstringtbl", 0x0141, 0, 0, 1 }, + { (uchar *) "getiosys", 0x0148, St|St2, 0, 2 }, + { (uchar *) "setiosys", 0x0149, 0, 0, 2 }, + { (uchar *) "linearsearch", 0x0150, St, 0, 8 }, + { (uchar *) "binarysearch", 0x0151, St, 0, 8 }, + { (uchar *) "linkedsearch", 0x0152, St, 0, 7 }, + { (uchar *) "callf", 0x0160, St, 0, 2 }, + { (uchar *) "callfi", 0x0161, St, 0, 3 }, + { (uchar *) "callfii", 0x0162, St, 0, 4 }, + { (uchar *) "callfiii", 0x0163, St, 0, 5 }, + { (uchar *) "streamunichar", 0x73, 0, GOP_Unicode, 1 }, + { (uchar *) "mzero", 0x170, 0, GOP_MemHeap, 2 }, + { (uchar *) "mcopy", 0x171, 0, GOP_MemHeap, 3 }, + { (uchar *) "malloc", 0x178, St, GOP_MemHeap, 2 }, + { (uchar *) "mfree", 0x179, 0, GOP_MemHeap, 1 }, + { (uchar *) "accelfunc", 0x180, 0, GOP_Acceleration, 2 }, + { (uchar *) "accelparam", 0x181, 0, GOP_Acceleration, 2 }, + { (uchar *) "numtof", 0x190, St, GOP_Float, 2 }, + { (uchar *) "ftonumz", 0x191, St, GOP_Float, 2 }, + { (uchar *) "ftonumn", 0x192, St, GOP_Float, 2 }, + { (uchar *) "ceil", 0x198, St, GOP_Float, 2 }, + { (uchar *) "floor", 0x199, St, GOP_Float, 2 }, + { (uchar *) "fadd", 0x1A0, St, GOP_Float, 3 }, + { (uchar *) "fsub", 0x1A1, St, GOP_Float, 3 }, + { (uchar *) "fmul", 0x1A2, St, GOP_Float, 3 }, + { (uchar *) "fdiv", 0x1A3, St, GOP_Float, 3 }, + { (uchar *) "fmod", 0x1A4, St|St2, GOP_Float, 4 }, + { (uchar *) "sqrt", 0x1A8, St, GOP_Float, 2 }, + { (uchar *) "exp", 0x1A9, St, GOP_Float, 2 }, + { (uchar *) "log", 0x1AA, St, GOP_Float, 2 }, + { (uchar *) "pow", 0x1AB, St, GOP_Float, 3 }, + { (uchar *) "sin", 0x1B0, St, GOP_Float, 2 }, + { (uchar *) "cos", 0x1B1, St, GOP_Float, 2 }, + { (uchar *) "tan", 0x1B2, St, GOP_Float, 2 }, + { (uchar *) "asin", 0x1B3, St, GOP_Float, 2 }, + { (uchar *) "acos", 0x1B4, St, GOP_Float, 2 }, + { (uchar *) "atan", 0x1B5, St, GOP_Float, 2 }, + { (uchar *) "atan2", 0x1B6, St, GOP_Float, 3 }, + { (uchar *) "jfeq", 0x1C0, Br, GOP_Float, 4 }, + { (uchar *) "jfne", 0x1C1, Br, GOP_Float, 4 }, + { (uchar *) "jflt", 0x1C2, Br, GOP_Float, 3 }, + { (uchar *) "jfle", 0x1C3, Br, GOP_Float, 3 }, + { (uchar *) "jfgt", 0x1C4, Br, GOP_Float, 3 }, + { (uchar *) "jfge", 0x1C5, Br, GOP_Float, 3 }, + { (uchar *) "jisnan", 0x1C8, Br, GOP_Float, 2 }, + { (uchar *) "jisinf", 0x1C9, Br, GOP_Float, 2 }, +}; + +/* The opmacros table is used for fake opcodes. The opcode numbers are + ignored; this table is only used for argument parsing. */ +static opcodeg opmacros_table_g[] = { + { (uchar *) "pull", 0, St, 0, 1 }, + { (uchar *) "push", 0, 0, 0, 1 }, +}; + +static opcodeg custom_opcode_g; + +static opcodez internal_number_to_opcode_z(int32 i) +{ opcodez x; + ASSERT_ZCODE(); + if (i == -1) return custom_opcode_z; + x = opcodes_table_z[i]; + if (instruction_set_number < x.version1) return invalid_opcode_z; + if (x.version2 == 0) return x; + if (instruction_set_number <= x.version2) return x; + i = x.extension; + if (i < 0) return invalid_opcode_z; + x = extension_table_z[i]; + if (instruction_set_number < x.version1) return invalid_opcode_z; + if (x.version2 == 0) return x; + if (instruction_set_number <= x.version2) return x; + return extension_table_z[x.extension]; +} + +static void make_opcode_syntax_z(opcodez opco) +{ char *p = "", *q = opcode_syntax_string; + sprintf(q, "%s", opco.name); + switch(opco.no) + { case ONE: p=" "; break; + case TWO: p=" "; break; + case EXT: + case VAR: p=" <0 to 4 operands>"; break; + case VAR_LONG: p=" <0 to 8 operands>"; break; + } + switch(opco.op_rules) + { case TEXT: sprintf(q+strlen(q), " "); return; + case LABEL: sprintf(q+strlen(q), "