From 9f712e2ebc23100581b5ca9d438c01dd6bf94ed3 Mon Sep 17 00:00:00 2001 From: belliash Date: Thu, 13 Aug 2020 13:58:37 +0200 Subject: [PATCH 01/32] Import readme and license. --- COPYING.md | 636 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 28 +++ 2 files changed, 664 insertions(+) create mode 100644 COPYING.md create mode 100644 README.md diff --git a/COPYING.md b/COPYING.md new file mode 100644 index 0000000..85c7c69 --- /dev/null +++ b/COPYING.md @@ -0,0 +1,636 @@ +# GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright (C) 2007 [Free Software Foundation, Inc.](http://fsf.org/) + +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 +[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/). + +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 +[http://www.gnu.org/philosophy/why-not-lgpl.html](http://www.gnu.org/philosophy/why-not-lgpl.html). diff --git a/README.md b/README.md new file mode 100644 index 0000000..46519e5 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +## XT Toolchain +This is a LLVM/Clang/LLD based mingw-w64 toolchain. It currently supports C and C++, and provides +a variety of tools including IDL, message and resource compilers. The XT Toolchain is also the +official build environment for compiling XT software, including the FerretOS. Currently, it is +targeted at Linux host only, however it should be possible to build it in MSYS2 as well. + +Benefits of a LLVM based MinGW toolchain are: + * Single toolchain targeting all architectures (i686, x86_64, armv7 and aarch64), + * Support for generating debug info in PDB format, + * Support for targeting ARM/AARCH64 architectures and ability to produce Windows ARM binaries. + +This software includes: + * CMake + * LLVM + * Make + * Mingw-w64 + * Ninja + * Wine + +This software is based on ["LLVM MinGW Toolchain"](https://github.com/mstorsjo/llvm-mingw). + +## Licensing +The XTchain project includes the scripts for building and assembling a toolchain as well as wrappers +for LLVM tools and environmental shell. These are licensed under the GPLv3 license. It covers only +mentioned components that are provided by XTchain directly. For more information on that, refer to +the COPYING.md file. The final pre-built toolchain is covered by the licenses of the individual, +external projects. The full list of software incorporated into this toolchain is available in the +README.md file. From ff2c349be35eb4197dcb9d965cb800f1e832e679 Mon Sep 17 00:00:00 2001 From: belliash Date: Thu, 13 Aug 2020 14:03:40 +0200 Subject: [PATCH 02/32] Correct typo in README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46519e5..1a57678 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This software includes: * Ninja * Wine -This software is based on ["LLVM MinGW Toolchain"](https://github.com/mstorsjo/llvm-mingw). +This software is based on [LLVM MinGW Toolchain](https://github.com/mstorsjo/llvm-mingw). ## Licensing The XTchain project includes the scripts for building and assembling a toolchain as well as wrappers From cf334d86ddcffb0c509abf3a5d3c73874f2d11be Mon Sep 17 00:00:00 2001 From: belliash Date: Fri, 14 Aug 2020 01:08:16 +0200 Subject: [PATCH 03/32] Import scripts and wrappers. --- scripts/clang-target-wrapper | 42 +++++++++++++++++++++++++++ scripts/dlltool-wrapper | 42 +++++++++++++++++++++++++++ scripts/ld-wrapper | 42 +++++++++++++++++++++++++++ scripts/objdump-wrapper | 46 ++++++++++++++++++++++++++++++ scripts/xtchain | 50 ++++++++++++++++++++++++++++++++ scripts/xtclib | 55 ++++++++++++++++++++++++++++++++++++ 6 files changed, 277 insertions(+) create mode 100755 scripts/clang-target-wrapper create mode 100755 scripts/dlltool-wrapper create mode 100755 scripts/ld-wrapper create mode 100755 scripts/objdump-wrapper create mode 100755 scripts/xtchain create mode 100755 scripts/xtclib diff --git a/scripts/clang-target-wrapper b/scripts/clang-target-wrapper new file mode 100755 index 0000000..58043e1 --- /dev/null +++ b/scripts/clang-target-wrapper @@ -0,0 +1,42 @@ +#!/bin/sh +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/clang-target-wrapper +# DESCRIPTION: CLANG Wrapper +# DEVELOPERS: Martin Storsjo +# Rafal Kupiec + + +# Set basic variables +DIR="$(cd $(dirname $0) && pwd)" +CLANG="$DIR/clang" +BASENAME="$(basename $0)" +TARGET="${BASENAME%-*}" +EXECUTABLE="${BASENAME##*-}" +DEFAULT_TARGET="x86_64-w64-mingw32" +ARCH="${TARGET%%-*}" + +# Set proper target +if [ "${TARGET}" = "${BASENAME}" ]; then + TARGET="${DEFAULT_TARGET}" +fi + +# Set lang-specific flags +case ${EXECUTABLE} in + "clang++"|"g++"|"c++") + FLAGS="$FLAGS --driver-mode=g++" + ;; + *) + FLAGS="" + ;; +esac + +# Set compiler flags +FLAGS="${FLAGS} -target ${TARGET}" +FLAGS="${FLAGS} -rtlib=compiler-rt" +FLAGS="${FLAGS} -stdlib=libc++" +FLAGS="${FLAGS} -fuse-ld=lld" +FLAGS="${FLAGS} -Qunused-arguments" + +# Launch the compiler +$CLANG $FLAGS "$@" diff --git a/scripts/dlltool-wrapper b/scripts/dlltool-wrapper new file mode 100755 index 0000000..09db3a3 --- /dev/null +++ b/scripts/dlltool-wrapper @@ -0,0 +1,42 @@ +#!/bin/sh +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/dlltool-wrapper +# DESCRIPTION: DLLTOOL Wrapper +# DEVELOPERS: Martin Storsjo +# Rafal Kupiec + + +# Set basic variables +DIR="$(cd $(dirname $0) && pwd)" +BASENAME="$(basename $0)" +TARGET="${BASENAME%-*}" +DEFAULT_TARGET="x86_64-w64-mingw32" + +# Update PATH +export PATH="$DIR":"$PATH" + +# Set proper target +if [ "${TARGET}" = "${BASENAME}" ]; then + TARGET="${DEFAULT_TARGET}" +fi + +# Set target machine +ARCH="${TARGET%%-*}" +case $ARCH in + aarch64) + M="arm64" + ;; + armv7) + M="arm" + ;; + i686) + M="i386" + ;; + x86_64) + M="i386:x86-64" + ;; +esac + +# Launch the utility +llvm-dlltool -m ${M} "$@" diff --git a/scripts/ld-wrapper b/scripts/ld-wrapper new file mode 100755 index 0000000..6fa9d39 --- /dev/null +++ b/scripts/ld-wrapper @@ -0,0 +1,42 @@ +#!/bin/sh +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/ld-wrapper +# DESCRIPTION: LLD Wrapper +# DEVELOPERS: Martin Storsjo +# Rafal Kupiec + + +# Set basic variables +DIR="$(cd $(dirname $0) && pwd)" +BASENAME="$(basename $0)" +TARGET="${BASENAME%-*}" +DEFAULT_TARGET="x86_64-w64-mingw32" + +# Update PATH +export PATH="${DIR}":"${PATH}" + +# Set proper target +if [ "${TARGET}" = "${BASENAME}" ]; then + TARGET="${DEFAULT_TARGET}" +fi + +# Set target machine +ARCH="${TARGET%%-*}" +case ${ARCH} in + aarch64) + M="arm64pe" + ;; + armv7) + M="thumb2pe" + ;; + i686) + M="i386pe" + ;; + x86_64) + M="i386pep" + ;; +esac + +# Launch the linker +ld.lld -m ${M} "$@" diff --git a/scripts/objdump-wrapper b/scripts/objdump-wrapper new file mode 100755 index 0000000..977551c --- /dev/null +++ b/scripts/objdump-wrapper @@ -0,0 +1,46 @@ +#!/bin/sh +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/objdump-wrapper +# DESCRIPTION: OBJDUMP Wrapper +# DEVELOPERS: Martin Storsjo +# Rafal Kupiec + + +# Set basic variables +DIR="$(cd $(dirname $0) && pwd)" + +# Update PATH +export PATH="$DIR":"$PATH" + +# Libtool can try to run objdump -f and wants to see certain strings in +# the output, to accept it being a valid windows (import) library +if [ "$1" = "-f" ]; then + llvm-readobj $2 | while read -r line; do + case $line in + File:*) + file=$(echo $line | awk '{print $2}') + ;; + Format:*) + format=$(echo $line | awk '{print $2}') + case $format in + COFF-i386) + format=pe-i386 + ;; + COFF-x86-64) + format=pe-x86-64 + ;; + COFF-ARM*) + # This is wrong; modern COFF armv7 isn't pe-arm-wince, and + # arm64 definitely isn't, but libtool wants to see this + # string (or some of the others) in order to accept it. + format=pe-arm-wince + ;; + esac + echo $file: file format $format + ;; + esac + done +else + llvm-objdump "$@" +fi diff --git a/scripts/xtchain b/scripts/xtchain new file mode 100755 index 0000000..63f6015 --- /dev/null +++ b/scripts/xtchain @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/xtchain +# DESCRIPTION: XTchain Entry Script +# DEVELOPERS: Rafal Kupiec + + +# Check if script launched as root +if [ "$(whoami)" = "root" ]; then + echo "This script cannot be run as root!" + exit 1 +fi + +# Get the absolute path to the XTchain +export XTCDIR="$(realpath $(dirname ${0}))" + +# Read the XTchain version +export XTCVER="$(cat ${XTCDIR}/Version)" + +# Load the library +source ${XTCDIR}/lib/xtchain/xtclib + +# Set the target architecture +: ${TARGET:=${1}} +: ${TARGET:=amd64} + +# Save the source directory +export SRCDIR="${2:-${PWD}}" + +# Make sure the compiler flags are clean +export HOST= +export CFLAGS= +export CXXFLAGS= +export LDFLAGS= + +# Update PATH +export PATH="${XTCDIR}/bin:${PATH}" + +# Display banner +version + +# Invoke shell with fancy prompt +export PFMAT1="\[\033[0;1;97;44m\]" +export PFMAT2="\[\033[0;34;104m\]" +export PFMAT3="\[\033[0;1;97;104m\]" +export PFMAT4="\[\033[0;94;49m\]" +export PFMAT5="\[\033[1;38;5;74m\]" +export PROMPT="\n${PFMAT1} XT Toolchain ${PFMAT2}${PFMAT3} \w ${PFMAT4}${PFMAT5} " +bash --rcfile <(echo 'source ~/.bashrc && export PS1="${PROMPT}" && cd ${SRCDIR}') diff --git a/scripts/xtclib b/scripts/xtclib new file mode 100755 index 0000000..c98f3e9 --- /dev/null +++ b/scripts/xtclib @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# PROJECT: XTchain +# LICENSE: See the COPYING.md in the top level directory +# FILE: scripts/xtclib +# DESCRIPTION: XTchain library +# DEVELOPERS: Rafal Kupiec + + +# Sets the target architecture +charch() +{ + if [ "x${1}" == "x" ]; then + echo "Syntax: charch [architecture]" + return + fi + case ${1} in + "aarch64"|"arm64") + export TARGET="aarch64" + ;; + "arm"|"armv7") + export TARGET="armv7" + ;; + "i386"|"i486"|"i586"|"i686"|"x86") + export TARGET="i686" + ;; + "amd64"|"x64"|"x86_64") + export TARGET="amd64" + ;; + *) + export TARGET="UNKNOWN" + esac + echo "Target Architecture: ${TARGET}" +} +export -f charch + +# Displays version banner +version() +{ + echo "###############################################################################" + echo "# XT Toolchain v${XTCVER} for Linux #" + echo "# by Rafal Kupiec #" + echo "###############################################################################" + echo + echo + echo "LLVM Compiler Version: $(${XTCDIR}/bin/clang --version | grep 'clang version' | cut -d' ' -f3)" + echo "LLVM Windres Utility Version: $(${XTCDIR}/generic-w64-mingw32/bin/windres-wrapper -V | cut -d' ' -f7)" + echo "Mingw IDL Compiler Version: $(${XTCDIR}/bin/i686-w64-mingw32-widl -V | grep 'version' | cut -d' ' -f5)" + echo "Wine Message Compiler Version: $(${XTCDIR}/bin/wmc -V | grep 'version' | cut -d' ' -f5)" + echo "Wine Resource Compiler Version: $(${XTCDIR}/bin/wrc --version | grep 'version' | cut -d' ' -f5)" + echo + charch ${TARGET} + echo + echo +} +export -f version From cfd2192e639619c96f0e9c5e8a536073f65c9e84 Mon Sep 17 00:00:00 2001 From: belliash Date: Fri, 14 Aug 2020 01:16:07 +0200 Subject: [PATCH 04/32] Add MinGW-W64 patch for SLTG support in WIDL. --- .../v7.0.0/001-widl-sltg-support.patch | 2020 +++++++++++++++++ 1 file changed, 2020 insertions(+) create mode 100644 patches/mingw-w64/v7.0.0/001-widl-sltg-support.patch diff --git a/patches/mingw-w64/v7.0.0/001-widl-sltg-support.patch b/patches/mingw-w64/v7.0.0/001-widl-sltg-support.patch new file mode 100644 index 0000000..73d39ef --- /dev/null +++ b/patches/mingw-w64/v7.0.0/001-widl-sltg-support.patch @@ -0,0 +1,2020 @@ +diff -apurN a/mingw-w64-tools/widl/Makefile.am b/mingw-w64-tools/widl/Makefile.am +--- a/mingw-w64-tools/widl/Makefile.am 2020-07-31 23:17:43.793863913 +0200 ++++ b/mingw-w64-tools/widl/Makefile.am 2020-07-31 21:16:36.330432306 +0200 +@@ -30,6 +30,7 @@ widl_SOURCES = src/widl.h \ + src/utils.c \ + src/widl.c \ + src/write_msft.c \ ++ src/write_sltg.c \ + src/wpp/wpp_private.h \ + src/wpp/ppy.tab.h \ + src/wpp/ppl.yy.c \ +diff -apurN a/mingw-w64-tools/widl/Makefile.in b/mingw-w64-tools/widl/Makefile.in +--- a/mingw-w64-tools/widl/Makefile.in 2020-07-31 23:17:43.793863913 +0200 ++++ b/mingw-w64-tools/widl/Makefile.in 2020-07-31 21:21:18.957064708 +0200 +@@ -117,7 +117,7 @@ am_widl_OBJECTS = src/widl-client.$(OBJE + src/widl-widl.$(OBJEXT) src/widl-write_msft.$(OBJEXT) \ + src/wpp/widl-ppl.yy.$(OBJEXT) src/wpp/widl-ppy.tab.$(OBJEXT) \ + src/wpp/widl-preproc.$(OBJEXT) src/wpp/widl-wpp.$(OBJEXT) \ +- src/widl-pathtools.$(OBJEXT) ++ src/widl-pathtools.$(OBJEXT) src/widl-write_sltg.$(OBJEXT) + widl_OBJECTS = $(am_widl_OBJECTS) + widl_LDADD = $(LDADD) + widl_LINK = $(CCLD) $(widl_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ +@@ -340,6 +340,7 @@ widl_SOURCES = src/widl.h \ + src/utils.c \ + src/widl.c \ + src/write_msft.c \ ++ src/write_sltg.c \ + src/wpp/wpp_private.h \ + src/wpp/ppy.tab.h \ + src/wpp/ppl.yy.c \ +@@ -513,6 +514,8 @@ src/widl-widl.$(OBJEXT): src/$(am__dirst + src/$(DEPDIR)/$(am__dirstamp) + src/widl-write_msft.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) ++src/widl-write_sltg.$(OBJEXT): src/$(am__dirstamp) \ ++ src/$(DEPDIR)/$(am__dirstamp) + src/wpp/$(am__dirstamp): + @$(MKDIR_P) src/wpp + @: > src/wpp/$(am__dirstamp) +@@ -559,6 +562,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/widl-utils.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/widl-widl.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/widl-write_msft.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/widl-write_sltg.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/port/$(DEPDIR)/widl-getopt.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/port/$(DEPDIR)/widl-getopt1.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/port/$(DEPDIR)/widl-port.Po@am__quote@ +@@ -835,6 +839,20 @@ src/widl-write_msft.obj: src/write_msft. + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -c -o src/widl-write_msft.obj `if test -f 'src/write_msft.c'; then $(CYGPATH_W) 'src/write_msft.c'; else $(CYGPATH_W) '$(srcdir)/src/write_msft.c'; fi` + ++src/widl-write_sltg.o: src/write_sltg.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -MT src/widl-write_sltg.o -MD -MP -MF src/$(DEPDIR)/widl-write_sltg.Tpo -c -o src/widl-write_sltg.o `test -f 'src/write_sltg.c' || echo '$(srcdir)/'`src/write_sltg.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/widl-write_sltg.Tpo src/$(DEPDIR)/widl-write_sltg.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/write_sltg.c' object='src/widl-write_sltg.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -c -o src/widl-write_sltg.o `test -f 'src/write_sltg.c' || echo '$(srcdir)/'`src/write_sltg.c ++ ++src/widl-write_sltg.obj: src/write_sltg.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -MT src/widl-write_sltg.obj -MD -MP -MF src/$(DEPDIR)/widl-write_sltg.Tpo -c -o src/widl-write_sltg.obj `if test -f 'src/write_sltg.c'; then $(CYGPATH_W) 'src/write_sltg.c'; else $(CYGPATH_W) '$(srcdir)/src/write_sltg.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/widl-write_sltg.Tpo src/$(DEPDIR)/widl-write_sltg.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/write_sltg.c' object='src/widl-write_sltg.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -c -o src/widl-write_sltg.obj `if test -f 'src/write_sltg.c'; then $(CYGPATH_W) 'src/write_sltg.c'; else $(CYGPATH_W) '$(srcdir)/src/write_sltg.c'; fi` ++ + src/wpp/widl-ppl.yy.o: src/wpp/ppl.yy.c + @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(widl_CPPFLAGS) $(CPPFLAGS) $(widl_CFLAGS) $(CFLAGS) -MT src/wpp/widl-ppl.yy.o -MD -MP -MF src/wpp/$(DEPDIR)/widl-ppl.yy.Tpo -c -o src/wpp/widl-ppl.yy.o `test -f 'src/wpp/ppl.yy.c' || echo '$(srcdir)/'`src/wpp/ppl.yy.c + @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/wpp/$(DEPDIR)/widl-ppl.yy.Tpo src/wpp/$(DEPDIR)/widl-ppl.yy.Po +diff -apurN a/mingw-w64-tools/widl/src/register.c b/mingw-w64-tools/widl/src/register.c +--- a/mingw-w64-tools/widl/src/register.c 2020-07-31 23:17:43.798863890 +0200 ++++ b/mingw-w64-tools/widl/src/register.c 2020-07-31 21:13:59.935209986 +0200 +@@ -286,7 +286,12 @@ void write_typelib_regscript( const stat + if (count && !strendswith( typelib_name, ".res" )) + error( "Cannot store multiple typelibs into %s\n", typelib_name ); + else +- create_msft_typelib( stmt->u.lib ); ++ { ++ if (do_old_typelib) ++ create_sltg_typelib( stmt->u.lib ); ++ else ++ create_msft_typelib( stmt->u.lib ); ++ } + count++; + } + if (count && strendswith( typelib_name, ".res" )) flush_output_resources( typelib_name ); +diff -apurN a/mingw-w64-tools/widl/src/typelib.h b/mingw-w64-tools/widl/src/typelib.h +--- a/mingw-w64-tools/widl/src/typelib.h 2020-07-31 23:17:43.537865053 +0200 ++++ b/mingw-w64-tools/widl/src/typelib.h 2020-07-31 21:13:59.935209986 +0200 +@@ -83,4 +83,5 @@ enum VARENUM { + extern unsigned short get_type_vt(type_t *t); + + extern int create_msft_typelib(typelib_t *typelib); ++extern int create_sltg_typelib(typelib_t *typelib); + #endif +diff -apurN a/mingw-w64-tools/widl/src/widl.c b/mingw-w64-tools/widl/src/widl.c +--- a/mingw-w64-tools/widl/src/widl.c 2020-07-31 23:17:43.799863886 +0200 ++++ b/mingw-w64-tools/widl/src/widl.c 2020-07-31 21:13:59.935209986 +0200 +@@ -62,6 +62,7 @@ static const char usage[] = + " -m32, -m64 Set the target architecture (Win32 or Win64)\n" + " -N Do not preprocess input\n" + " --oldnames Use old naming conventions\n" ++" --oldtlb Use old typelib (SLTG) format\n" + " -o, --output=NAME Set the output file name\n" + " -Otype Type of stubs to generate (-Os, -Oi, -Oif)\n" + " -p Generate proxy\n" +@@ -114,6 +115,7 @@ int do_everything = 1; + static int preprocess_only = 0; + int do_header = 0; + int do_typelib = 0; ++int do_old_typelib = 0; + int do_proxies = 0; + int do_client = 0; + int do_server = 0; +@@ -164,6 +166,7 @@ enum { + DLLDATA_OPTION, + DLLDATA_ONLY_OPTION, + LOCAL_STUBS_OPTION, ++ OLD_TYPELIB_OPTION, + PREFIX_ALL_OPTION, + PREFIX_CLIENT_OPTION, + PREFIX_SERVER_OPTION, +@@ -188,6 +191,7 @@ static const struct option long_options[ + { "local-stubs", 1, NULL, LOCAL_STUBS_OPTION }, + { "ns_prefix", 0, NULL, RT_NS_PREFIX }, + { "oldnames", 0, NULL, OLDNAMES_OPTION }, ++ { "oldtlb", 0, NULL, OLD_TYPELIB_OPTION }, + { "output", 0, NULL, 'o' }, + { "prefix-all", 1, NULL, PREFIX_ALL_OPTION }, + { "prefix-client", 1, NULL, PREFIX_CLIENT_OPTION }, +@@ -325,6 +329,7 @@ static void set_everything(int x) + { + do_header = x; + do_typelib = x; ++ do_old_typelib = x; + do_proxies = x; + do_client = x; + do_server = x; +@@ -712,6 +717,9 @@ int main(int argc,char *argv[]) + do_everything = 0; + do_typelib = 1; + break; ++ case OLD_TYPELIB_OPTION: ++ do_old_typelib = 1; ++ break; + case 'T': + typelib_name = xstrdup(optarg); + break; +diff -apurN a/mingw-w64-tools/widl/src/widl.h b/mingw-w64-tools/widl/src/widl.h +--- a/mingw-w64-tools/widl/src/widl.h 2020-07-31 23:17:43.537865053 +0200 ++++ b/mingw-w64-tools/widl/src/widl.h 2020-07-31 21:13:59.935209986 +0200 +@@ -38,6 +38,7 @@ extern int pedantic; + extern int do_everything; + extern int do_header; + extern int do_typelib; ++extern int do_old_typelib; + extern int do_proxies; + extern int do_client; + extern int do_server; +diff -apurN a/mingw-w64-tools/widl/src/write_sltg.c b/mingw-w64-tools/widl/src/write_sltg.c +--- a/mingw-w64-tools/widl/src/write_sltg.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/mingw-w64-tools/widl/src/write_sltg.c 2020-07-31 21:13:59.936209981 +0200 +@@ -0,0 +1,1857 @@ ++/* ++ * Typelib (SLTG) generation ++ * ++ * Copyright 2015,2016 Dmitry Timoshkov ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include "config.h" ++#include "wine/port.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NONAMELESSUNION ++ ++#include "windef.h" ++#include "winbase.h" ++ ++#include "widl.h" ++#include "typelib.h" ++#include "typelib_struct.h" ++#include "utils.h" ++#include "header.h" ++#include "typetree.h" ++ ++static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } }; ++ ++struct sltg_data ++{ ++ int size, allocated; ++ char *data; ++}; ++ ++struct sltg_library ++{ ++ short name; ++ char *helpstring; ++ char *helpfile; ++ int helpcontext; ++ int syskind; ++ LCID lcid; ++ int libflags; ++ int version; ++ GUID uuid; ++}; ++ ++struct sltg_block ++{ ++ int length; ++ int index_string; ++ void *data; ++ struct sltg_block *next; ++}; ++ ++struct sltg_typelib ++{ ++ typelib_t *typelib; ++ struct sltg_data index; ++ struct sltg_data name_table; ++ struct sltg_library library; ++ struct sltg_block *blocks; ++ int n_file_blocks; ++ int first_block; ++ int typeinfo_count; ++ int typeinfo_size; ++ struct sltg_block *typeinfo; ++}; ++ ++struct sltg_hrefmap ++{ ++ int href_count; ++ int *href; ++}; ++ ++#include "pshpack1.h" ++struct sltg_typeinfo_header ++{ ++ short magic; ++ int href_offset; ++ int res06; ++ int member_offset; ++ int res0e; ++ int version; ++ int res16; ++ struct ++ { ++ unsigned unknown1 : 3; ++ unsigned flags : 13; ++ unsigned unknown2 : 8; ++ unsigned typekind : 8; ++ } misc; ++ int res1e; ++}; ++ ++struct sltg_member_header ++{ ++ short res00; ++ short res02; ++ char res04; ++ int extra; ++}; ++ ++struct sltg_variable ++{ ++ char magic; /* 0x0a */ ++ char flags; ++ short next; ++ short name; ++ short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */ ++ short type; /* if flags & 0x02 this is the type, else offset to type */ ++ int memid; ++ short helpcontext; ++ short helpstring; ++ short varflags; /* only present if magic & 0x02 */ ++}; ++ ++struct sltg_tail ++{ ++ short cFuncs; ++ short cVars; ++ short cImplTypes; ++ short res06; /* always 0000 */ ++ short funcs_off; /* offset to functions (starting from the member header) */ ++ short vars_off; /* offset to vars (starting from the member header) */ ++ short impls_off; /* offset to implemented types (starting from the member header) */ ++ short funcs_bytes; /* bytes used by function data */ ++ short vars_bytes; /* bytes used by var data */ ++ short impls_bytes; /* bytes used by implemented type data */ ++ short tdescalias_vt; /* for TKIND_ALIAS */ ++ short res16; /* always ffff */ ++ short res18; /* always 0000 */ ++ short res1a; /* always 0000 */ ++ short simple_alias; /* tdescalias_vt is a vt rather than an offset? */ ++ short res1e; /* always 0000 */ ++ short cbSizeInstance; ++ short cbAlignment; ++ short res24; ++ short res26; ++ short cbSizeVft; ++ short res2a; /* always ffff */ ++ short res2c; /* always ffff */ ++ short res2e; /* always ffff */ ++ short res30; /* always ffff */ ++ short res32; /* unknown */ ++ short type_bytes; /* bytes used by type descriptions */ ++}; ++ ++struct sltg_hrefinfo ++{ ++ char magic; /* 0xdf */ ++ char res01; /* 0x00 */ ++ int res02; /* 0xffffffff */ ++ int res06; /* 0xffffffff */ ++ int res0a; /* 0xffffffff */ ++ int res0e; /* 0xffffffff */ ++ int res12; /* 0xffffffff */ ++ int res16; /* 0xffffffff */ ++ int res1a; /* 0xffffffff */ ++ int res1e; /* 0xffffffff */ ++ int res22; /* 0xffffffff */ ++ int res26; /* 0xffffffff */ ++ int res2a; /* 0xffffffff */ ++ int res2e; /* 0xffffffff */ ++ int res32; /* 0xffffffff */ ++ int res36; /* 0xffffffff */ ++ int res3a; /* 0xffffffff */ ++ int res3e; /* 0xffffffff */ ++ short res42;/* 0xffff */ ++ int number; /* this is 8 times the number of refs */ ++ /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ ++ ++ short res50;/* 0xffff */ ++ char res52; /* 0x01 */ ++ int res53; /* 0x00000000 */ ++ /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii ++ * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the ++ * ref refers to the nth type listed in this library (0 based). Else ++ * the xxxx (which maybe fewer than 4 digits) is the offset into the name ++ * table to a string "*\G{}#1.0#0#C:\WINNT\System32\stdole32.tlb#" ++ * The guid is the typelib guid; the ref again refers to the nth type of ++ * the imported typelib. ++ */ ++ ++ char resxx; /* 0xdf */ ++}; ++ ++struct sltg_function ++{ ++ char magic; /* 0x4c, 0xcb or 0x8b with optional SLTG_FUNCTION_FLAGS_PRESENT flag */ ++ char flags; /* high nibble is INVOKE_KIND, low nibble = 2 */ ++ short next; /* byte offset from beginning of group to next fn */ ++ short name; /* Offset within name table to name */ ++ int dispid; /* dispid */ ++ short helpcontext; /* helpcontext (again 1 is special) */ ++ short helpstring; /* helpstring offset to offset */ ++ short arg_off; /* offset to args from start of block */ ++ char nacc; /* lowest 3bits are CALLCONV, rest are no of args */ ++ char retnextopt; /* if 0x80 bit set ret type follows else next WORD ++ is offset to ret type. No of optional args is ++ middle 6 bits */ ++ short rettype; /* return type VT_?? or offset to ret type */ ++ short vtblpos; /* position in vtbl? */ ++ short funcflags; /* present if magic & 0x20 */ ++/* Param list starts, repeat next two as required */ ++#if 0 ++ WORD name; /* offset to 2nd letter of name */ ++ WORD+ type; /* VT_ of param */ ++#endif ++}; ++ ++struct sltg_impl_info ++{ ++ short res00; ++ short next; ++ short res04; ++ char impltypeflags; ++ char res07; ++ short res08; ++ short ref; ++ short res0c; ++ short res0e; ++ short res10; ++ short res12; ++ short pos; ++}; ++ ++#include "poppack.h" ++ ++static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type); ++static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type); ++static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type); ++static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type); ++static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type); ++ ++static void init_sltg_data(struct sltg_data *data) ++{ ++ data->size = 0; ++ data->allocated = 0x10; ++ data->data = xmalloc(0x10); ++} ++ ++static int add_index(struct sltg_data *index, const char *name) ++{ ++ int name_offset = index->size; ++ int new_size = index->size + strlen(name) + 1; ++ ++ chat("add_index: name_offset %d, \"%s\"\n", name_offset, name); ++ ++ if (new_size > index->allocated) ++ { ++ index->allocated = max(index->allocated * 2, new_size); ++ index->data = xrealloc(index->data, index->allocated); ++ } ++ ++ strcpy(index->data + index->size, name); ++ index->size = new_size; ++ ++ return name_offset; ++} ++ ++static void init_index(struct sltg_data *index) ++{ ++ static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 }; ++ ++ init_sltg_data(index); ++ ++ add_index(index, compobj); ++} ++ ++static int add_name(struct sltg_typelib *sltg, const char *name) ++{ ++ int name_offset = sltg->name_table.size; ++ int new_size = sltg->name_table.size + strlen(name) + 1 + 8; ++ int aligned_size; ++ ++ chat("add_name: %s\n", name); ++ ++ aligned_size = (new_size + 0x1f) & ~0x1f; ++ if (aligned_size - new_size < 4) ++ new_size = aligned_size; ++ else ++ new_size = (new_size + 1) & ~1; ++ ++ if (new_size > sltg->name_table.allocated) ++ { ++ sltg->name_table.allocated = max(sltg->name_table.allocated * 2, new_size); ++ sltg->name_table.data = xrealloc(sltg->name_table.data, sltg->name_table.allocated); ++ } ++ ++ memset(sltg->name_table.data + sltg->name_table.size, 0xff, 8); ++ strcpy(sltg->name_table.data + sltg->name_table.size + 8, name); ++ sltg->name_table.size = new_size; ++ sltg->name_table.data[sltg->name_table.size - 1] = 0; /* clear alignment */ ++ ++ return name_offset; ++} ++ ++static void init_name_table(struct sltg_typelib *sltg) ++{ ++ init_sltg_data(&sltg->name_table); ++} ++ ++static void init_library(struct sltg_typelib *sltg) ++{ ++ const attr_t *attr; ++ ++ sltg->library.name = add_name(sltg, sltg->typelib->name); ++ sltg->library.helpstring = NULL; ++ sltg->library.helpcontext = 0; ++ sltg->library.syskind = (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32; ++ sltg->library.lcid = 0x0409; ++ sltg->library.libflags = 0; ++ sltg->library.version = 0; ++ sltg->library.helpfile = NULL; ++ memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid)); ++ ++ if (!sltg->typelib->attrs) return; ++ ++ LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry) ++ { ++ const expr_t *expr; ++ ++ switch (attr->type) ++ { ++ case ATTR_VERSION: ++ sltg->library.version = attr->u.ival; ++ break; ++ case ATTR_HELPSTRING: ++ sltg->library.helpstring = attr->u.pval; ++ break; ++ case ATTR_HELPFILE: ++ sltg->library.helpfile = attr->u.pval; ++ break; ++ case ATTR_UUID: ++ sltg->library.uuid = *(GUID *)attr->u.pval; ++ break; ++ case ATTR_HELPCONTEXT: ++ expr = attr->u.pval; ++ sltg->library.helpcontext = expr->cval; ++ break; ++ case ATTR_LIBLCID: ++ expr = attr->u.pval; ++ sltg->library.lcid = expr->cval; ++ break; ++ case ATTR_CONTROL: ++ sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */ ++ break; ++ case ATTR_HIDDEN: ++ sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */ ++ break; ++ case ATTR_RESTRICTED: ++ sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */ ++ break; ++ default: ++ break; ++ } ++ } ++} ++ ++static void add_block_index(struct sltg_typelib *sltg, void *data, int size, int index) ++{ ++ struct sltg_block *block = xmalloc(sizeof(*block)); ++ ++ block->length = size; ++ block->data = data; ++ block->index_string = index; ++ block->next = NULL; ++ ++ if (sltg->blocks) ++ { ++ struct sltg_block *blocks = sltg->blocks; ++ ++ while (blocks->next) ++ blocks = blocks->next; ++ ++ blocks->next = block; ++ } ++ else ++ sltg->blocks = block; ++ ++ sltg->n_file_blocks++; ++} ++ ++static void add_block(struct sltg_typelib *sltg, void *data, int size, const char *name) ++{ ++ struct sltg_block *block = xmalloc(sizeof(*block)); ++ int index; ++ ++ chat("add_block: %p,%d,\"%s\"\n", data, size, name); ++ ++ index = add_index(&sltg->index, name); ++ ++ add_block_index(sltg, data, size, index); ++} ++ ++static void *create_library_block(struct sltg_typelib *typelib, int *size, int *index) ++{ ++ void *block; ++ short *p; ++ ++ *size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID); ++ if (typelib->library.helpstring) *size += strlen(typelib->library.helpstring); ++ if (typelib->library.helpfile) *size += strlen(typelib->library.helpfile); ++ ++ block = xmalloc(*size); ++ p = block; ++ *p++ = 0x51cc; /* magic */ ++ *p++ = 3; /* res02 */ ++ *p++ = typelib->library.name; ++ *p++ = 0xffff; /* res06 */ ++ if (typelib->library.helpstring) ++ { ++ *p++ = strlen(typelib->library.helpstring); ++ strcpy((char *)p, typelib->library.helpstring); ++ p = (short *)((char *)p + strlen(typelib->library.helpstring)); ++ } ++ else ++ *p++ = 0xffff; ++ if (typelib->library.helpfile) ++ { ++ *p++ = strlen(typelib->library.helpfile); ++ strcpy((char *)p, typelib->library.helpfile); ++ p = (short *)((char *)p + strlen(typelib->library.helpfile)); ++ } ++ else ++ *p++ = 0xffff; ++ *(int *)p = typelib->library.helpcontext; ++ p += 2; ++ *p++ = typelib->library.syskind; ++ *p++ = typelib->library.lcid; ++ *(int *)p = 0; /* res12 */ ++ p += 2; ++ *p++ = typelib->library.libflags; ++ *(int *)p = typelib->library.version; ++ p += 2; ++ *(GUID *)p = typelib->library.uuid; ++ ++ *index = add_index(&typelib->index, "dir"); ++ ++ return block; ++} ++ ++static const char *new_index_name(void) ++{ ++ static char name[11] = "0000000000"; ++ static int pos = 0; ++ char *new_name; ++ ++ if (name[pos] == 'Z') ++ { ++ pos++; ++ if (pos > 9) ++ error("too many index names\n"); ++ } ++ ++ name[pos]++; ++ ++ new_name = xmalloc(sizeof(name)); ++ strcpy(new_name, name); ++ return new_name; ++} ++ ++static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int size, const char *name) ++{ ++ struct sltg_block *block = xmalloc(sizeof(*block)); ++ ++ chat("sltg_add_typeinfo: %p,%d,%s\n", data, size, name); ++ ++ block->length = size; ++ block->data = data; ++ block->index_string = 0; ++ block->next = NULL; ++ ++ if (sltg->typeinfo) ++ { ++ struct sltg_block *typeinfo = sltg->typeinfo; ++ ++ while (typeinfo->next) ++ typeinfo = typeinfo->next; ++ ++ typeinfo->next = block; ++ } ++ else ++ sltg->typeinfo = block; ++ ++ sltg->typeinfo_count++; ++ sltg->typeinfo_size += size; ++} ++ ++static void append_data(struct sltg_data *block, const void *data, int size) ++{ ++ int new_size = block->size + size; ++ ++ if (new_size > block->allocated) ++ { ++ block->allocated = max(block->allocated * 2, new_size); ++ block->data = xrealloc(block->data, block->allocated); ++ } ++ ++ memcpy(block->data + block->size, data, size); ++ block->size = new_size; ++} ++ ++static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type) ++{ ++ error("add_module_typeinfo: %s not implemented\n", type->name); ++} ++ ++static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, int kind) ++{ ++ const char *index_name, *other_name; ++ void *block; ++ short *p; ++ int size, helpcontext = 0; ++ GUID guid = { 0 }; ++ const expr_t *expr; ++ ++ index_name = new_index_name(); ++ other_name = new_index_name(); ++ ++ expr = get_attrp(type->attrs, ATTR_HELPCONTEXT); ++ if (expr) helpcontext = expr->cval; ++ ++ p = get_attrp(type->attrs, ATTR_UUID); ++ if (p) guid = *(GUID *)p; ++ ++ size = sizeof(short) * 8 + 10 /* index_name */ * 2 + sizeof(int) + sizeof(GUID); ++ ++ block = xmalloc(size); ++ p = block; ++ *p++ = strlen(index_name); ++ strcpy((char *)p, index_name); ++ p = (short *)((char *)p + strlen(index_name)); ++ *p++ = strlen(other_name); ++ strcpy((char *)p, other_name); ++ p = (short *)((char *)p + strlen(other_name)); ++ *p++ = -1; /* res1a */ ++ *p++ = add_name(typelib, type->name); /* name offset */ ++ *p++ = 0; /* FIXME: helpstring */ ++ *p++ = -1; /* res20 */ ++ *(int *)p = helpcontext; ++ p += 2; ++ *p++ = -1; /* res26 */ ++ *(GUID *)p = guid; ++ p += sizeof(GUID)/2; ++ *p = kind; ++ ++ sltg_add_typeinfo(typelib, block, size, index_name); ++ ++ return index_name; ++} ++ ++static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind, ++ const struct sltg_hrefmap *hrefmap) ++{ ++ ti->magic = 0x0501; ++ ti->href_offset = -1; ++ ti->res06 = -1; ++ ti->res0e = -1; ++ ti->version = get_attrv(type->attrs, ATTR_VERSION); ++ ti->res16 = 0xfffe0000; ++ ti->misc.unknown1 = 0x02; ++ ti->misc.flags = 0; /* FIXME */ ++ ti->misc.unknown2 = 0x02; ++ ti->misc.typekind = kind; ++ ti->res1e = 0; ++ ++ ti->member_offset = sizeof(*ti); ++ ++ if (hrefmap->href_count) ++ { ++ char name[64]; ++ int i, hrefinfo_size; ++ ++ hrefinfo_size = sizeof(struct sltg_hrefinfo); ++ ++ for (i = 0; i < hrefmap->href_count; i++) ++ { ++ sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); ++ hrefinfo_size += 8 + 2 + strlen(name); ++ } ++ ++ ti->href_offset = ti->member_offset; ++ ti->member_offset += hrefinfo_size; ++ } ++} ++ ++static void init_sltg_tail(struct sltg_tail *tail) ++{ ++ tail->cFuncs = 0; ++ tail->cVars = 0; ++ tail->cImplTypes = 0; ++ tail->res06 = 0; ++ tail->funcs_off = -1; ++ tail->vars_off = -1; ++ tail->impls_off = -1; ++ tail->funcs_bytes = -1; ++ tail->vars_bytes = -1; ++ tail->impls_bytes = -1; ++ tail->tdescalias_vt = -1; ++ tail->res16 = -1; ++ tail->res18 = 0; ++ tail->res1a = 0; ++ tail->simple_alias = 0; ++ tail->res1e = 0; ++ tail->cbSizeInstance = 0; ++ tail->cbAlignment = 4; ++ tail->res24 = -1; ++ tail->res26 = -1; ++ tail->cbSizeVft = 0; ++ tail->res2a = -1; ++ tail->res2c = -1; ++ tail->res2e = -1; ++ tail->res30 = -1; ++ tail->res32 = 0; ++ tail->type_bytes = 0; ++} ++ ++static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap) ++{ ++ struct sltg_hrefinfo hrefinfo; ++ char name[64]; ++ int i; ++ ++ if (!hrefmap->href_count) return; ++ ++ hrefinfo.magic = 0xdf; ++ hrefinfo.res01 = 0; ++ hrefinfo.res02 = -1; ++ hrefinfo.res06 = -1; ++ hrefinfo.res0a = -1; ++ hrefinfo.res0e = -1; ++ hrefinfo.res12 = -1; ++ hrefinfo.res16 = -1; ++ hrefinfo.res1a = -1; ++ hrefinfo.res1e = -1; ++ hrefinfo.res22 = -1; ++ hrefinfo.res26 = -1; ++ hrefinfo.res2a = -1; ++ hrefinfo.res2e = -1; ++ hrefinfo.res32 = -1; ++ hrefinfo.res36 = -1; ++ hrefinfo.res3a = -1; ++ hrefinfo.res3e = -1; ++ hrefinfo.res42 = -1; ++ hrefinfo.number = hrefmap->href_count * 8; ++ hrefinfo.res50 = -1; ++ hrefinfo.res52 = 1; ++ hrefinfo.res53 = 0; ++ hrefinfo.resxx = 0xdf; ++ ++ append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50)); ++ ++ for (i = 0; i < hrefmap->href_count; i++) ++ append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8); ++ ++ append_data(data, &hrefinfo.res50, 7); ++ ++ for (i = 0; i < hrefmap->href_count; i++) ++ { ++ short len; ++ ++ sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]); ++ len = strlen(name); ++ ++ append_data(data, &len, sizeof(len)); ++ append_data(data, name, len); ++ } ++ ++ append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx)); ++} ++ ++static void dump_var_desc(const char *data, int size) ++{ ++ const unsigned char *p = (const unsigned char *)data; ++ int i; ++ ++ if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return; ++ ++ chat("dump_var_desc: size %d bytes\n", size); ++ ++ for (i = 0; i < size; i++) ++ fprintf(stderr, " %02x", *p++); ++ ++ fprintf(stderr, "\n"); ++} ++ ++static int get_element_size(type_t *type) ++{ ++ int vt = get_type_vt(type); ++ ++ switch (vt) ++ { ++ case VT_I1: ++ case VT_UI1: ++ return 1; ++ ++ case VT_INT: ++ case VT_UINT: ++ return /* typelib_kind == SYS_WIN16 ? 2 : */ 4; ++ ++ case VT_UI2: ++ case VT_I2: ++ case VT_BOOL: ++ return 2; ++ ++ case VT_I4: ++ case VT_UI4: ++ case VT_R4: ++ case VT_ERROR: ++ case VT_HRESULT: ++ return 4; ++ ++ case VT_R8: ++ case VT_I8: ++ case VT_UI8: ++ case VT_CY: ++ case VT_DATE: ++ return 8; ++ ++ case VT_DECIMAL: ++ return 16; ++ ++ case VT_PTR: ++ case VT_UNKNOWN: ++ case VT_DISPATCH: ++ case VT_BSTR: ++ case VT_LPSTR: ++ case VT_LPWSTR: ++ return pointer_size; ++ ++ case VT_VOID: ++ return 0; ++ ++ case VT_VARIANT: ++ return pointer_size == 8 ? 24 : 16; ++ ++ case VT_USERDEFINED: ++ return 0; ++ ++ default: ++ error("get_element_size: unrecognized vt %d\n", vt); ++ break; ++ } ++ ++ return 0; ++} ++ ++static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href) ++{ ++ int i, href = -1; ++ ++ for (i = 0; i < hrefmap->href_count; i++) ++ { ++ if (hrefmap->href[i] == typelib_href) ++ { ++ href = i; ++ break; ++ } ++ } ++ ++ if (href == -1) ++ { ++ href = hrefmap->href_count; ++ ++ if (hrefmap->href) ++ hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1)); ++ else ++ hrefmap->href = xmalloc(sizeof(*hrefmap->href)); ++ ++ hrefmap->href[hrefmap->href_count] = typelib_href; ++ hrefmap->href_count++; ++ } ++ ++ chat("typelib href %d mapped to local href %d\n", typelib_href, href); ++ ++ return href << 2; ++} ++ ++static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short param_flags, ++ short flags, short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap) ++{ ++ short vt, vt_flags, desc_offset; ++ ++ chat("write_var_desc: type %p, type->name %s\n", ++ type, type->name ? type->name : "NULL"); ++ ++ if (is_array(type) && !type_array_is_decl_as_ptr(type)) ++ { ++ int num_dims, elements, array_start, size, array_size; ++ type_t *atype; ++ struct ++ { ++ short cDims; ++ short fFeatures; ++ int cbElements; ++ int cLocks; ++ void *pvData; ++ int bound[2]; ++ } *array; ++ int *bound; ++ short vt_off[2]; ++ ++ elements = 1; ++ num_dims = 0; ++ ++ atype = type; ++ ++ while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) ++ { ++ num_dims++; ++ elements *= type_array_get_dim(atype); ++ ++ atype = type_array_get_element_type(atype); ++ } ++ ++ chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements); ++ ++ array_start = data->size; ++ ++ size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */; ++ array = xmalloc(size); ++ ++ array->cDims = num_dims; ++ array->fFeatures = 0x0004; /* FADF_EMBEDDED */ ++ array->cbElements = get_element_size(atype); ++ array->cLocks = 0; ++ array->pvData = NULL; ++ ++ bound = array->bound; ++ ++ array_size = array->cbElements; ++ atype = type; ++ ++ while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) ++ { ++ bound[0] = type_array_get_dim(atype); ++ array_size *= bound[0]; ++ bound[1] = 0; ++ bound += 2; ++ ++ atype = type_array_get_element_type(atype); ++ } ++ ++ if (size_instance) ++ { ++ *size_instance += array_size; ++ size_instance = NULL; /* don't account for element size */ ++ } ++ ++ append_data(data, array, size); ++ ++ desc_offset = data->size; ++ ++ vt_off[0] = VT_CARRAY; ++ vt_off[1] = array_start + base_offset; ++ append_data(data, vt_off, sizeof(vt_off)); ++ ++ /* fall through to write array element description */ ++ type = atype; ++ } ++ else ++ desc_offset = data->size; ++ ++ vt = get_type_vt(type); ++ ++ if (vt == VT_PTR) ++ { ++ type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type); ++ ++ if (is_ptr(ref)) ++ { ++ chat("write_var_desc: vt VT_PTR | 0x0400 | %04x\n", param_flags); ++ vt = VT_PTR | 0x0400 | param_flags; ++ append_data(data, &vt, sizeof(vt)); ++ write_var_desc(typelib, data, ref, 0, 0, base_offset, size_instance, hrefmap); ++ } ++ else ++ write_var_desc(typelib, data, ref, param_flags, 0x0e00, base_offset, size_instance, hrefmap); ++ return desc_offset; ++ } ++ ++ chat("write_var_desc: vt %d, flags %04x\n", vt, flags); ++ ++ vt_flags = vt | flags | param_flags; ++ append_data(data, &vt_flags, sizeof(vt_flags)); ++ ++ if (vt == VT_USERDEFINED) ++ { ++ short href; ++ ++ while (type->typelib_idx < 0 && type_is_alias(type)) ++ type = type_alias_get_aliasee_type(type); ++ ++ chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n", ++ type, type->name, type_get_type(type), type->typelib_idx); ++ ++ if (type->typelib_idx == -1) ++ { ++ chat("write_var_desc: trying to ref not added type\n"); ++ ++ switch (type_get_type(type)) ++ { ++ case TYPE_STRUCT: ++ add_structure_typeinfo(typelib, type); ++ break; ++ case TYPE_INTERFACE: ++ add_interface_typeinfo(typelib, type); ++ break; ++ case TYPE_ENUM: ++ add_enum_typeinfo(typelib, type); ++ break; ++ case TYPE_UNION: ++ add_union_typeinfo(typelib, type); ++ break; ++ case TYPE_COCLASS: ++ add_coclass_typeinfo(typelib, type); ++ break; ++ default: ++ error("write_var_desc: VT_USERDEFINED - unhandled type %d\n", ++ type_get_type(type)); ++ } ++ } ++ ++ if (type->typelib_idx == -1) ++ error("write_var_desc: trying to ref not added type\n"); ++ ++ href = local_href(hrefmap, type->typelib_idx); ++ chat("write_var_desc: VT_USERDEFINED, local href %d\n", href); ++ ++ append_data(data, &href, sizeof(href)); ++ } ++ ++ if (size_instance) ++ *size_instance += get_element_size(type); ++ ++ return desc_offset; ++} ++ ++static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) ++{ ++ struct sltg_data data, *var_data = NULL; ++ struct sltg_hrefmap hrefmap; ++ const char *index_name; ++ struct sltg_typeinfo_header ti; ++ struct sltg_member_header member; ++ struct sltg_tail tail; ++ int member_offset, var_count = 0, var_data_size = 0, size_instance = 0; ++ short *type_desc_offset = NULL; ++ ++ if (type->typelib_idx != -1) return; ++ ++ chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name); ++ ++ type->typelib_idx = typelib->n_file_blocks; ++ ++ hrefmap.href_count = 0; ++ hrefmap.href = NULL; ++ ++ if (type_struct_get_fields(type)) ++ { ++ int i = 0; ++ var_t *var; ++ ++ var_count = list_count(type_struct_get_fields(type)); ++ ++ var_data = xmalloc(var_count * sizeof(*var_data)); ++ type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset)); ++ ++ LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) ++ { ++ short base_offset; ++ ++ chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n", ++ var, var->name, var->declspec.type, var->declspec.type->name); ++ ++ init_sltg_data(&var_data[i]); ++ ++ base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable); ++ type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->declspec.type, 0, 0, ++ base_offset, &size_instance, &hrefmap); ++ dump_var_desc(var_data[i].data, var_data[i].size); ++ ++ if (var_data[i].size > sizeof(short)) ++ var_data_size += var_data[i].size; ++ i++; ++ } ++ } ++ ++ init_sltg_data(&data); ++ ++ index_name = add_typeinfo_block(typelib, type, TKIND_RECORD); ++ ++ init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap); ++ append_data(&data, &ti, sizeof(ti)); ++ ++ write_hrefmap(&data, &hrefmap); ++ ++ member_offset = data.size; ++ ++ member.res00 = 0x0001; ++ member.res02 = 0xffff; ++ member.res04 = 0x01; ++ member.extra = var_data_size + var_count * sizeof(struct sltg_variable); ++ append_data(&data, &member, sizeof(member)); ++ ++ var_data_size = 0; ++ ++ if (type_struct_get_fields(type)) ++ { ++ int i = 0; ++ short next = member_offset; ++ var_t *var; ++ ++ LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) ++ { ++ struct sltg_variable variable; ++ ++ next += sizeof(variable); ++ ++ variable.magic = 0x2a; /* always write flags to simplify calculations */ ++ variable.name = add_name(typelib, var->name); ++ variable.byte_offs = 0; ++ if (var_data[i].size > sizeof(short)) ++ { ++ variable.flags = 0; ++ var_data_size = next - member_offset + type_desc_offset[i]; ++ variable.type = var_data_size; ++ next += var_data[i].size; ++ } ++ else ++ { ++ variable.flags = 0x02; ++ variable.type = *(short *)var_data[i].data; ++ } ++ variable.next = i < var_count - 1 ? next - member_offset : -1; ++ variable.memid = 0x40000000 + i; ++ variable.helpcontext = -2; /* 0xfffe */ ++ variable.helpstring = -1; ++ variable.varflags = 0; ++ ++ append_data(&data, &variable, sizeof(variable)); ++ if (var_data[i].size > sizeof(short)) ++ append_data(&data, var_data[i].data, var_data[i].size); ++ ++ i++; ++ } ++ } ++ ++ init_sltg_tail(&tail); ++ ++ tail.cVars = var_count; ++ tail.vars_off = 0; ++ tail.vars_bytes = var_data_size; ++ tail.cbSizeInstance = size_instance; ++ tail.type_bytes = data.size - member_offset - sizeof(member); ++ append_data(&data, &tail, sizeof(tail)); ++ ++ add_block(typelib, data.data, data.size, index_name); ++} ++ ++static importinfo_t *find_importinfo(typelib_t *typelib, const char *name) ++{ ++ importlib_t *importlib; ++ ++ LIST_FOR_EACH_ENTRY(importlib, &typelib->importlibs, importlib_t, entry) ++ { ++ int i; ++ ++ for (i = 0; i < importlib->ntypeinfos; i++) ++ { ++ if (!strcmp(name, importlib->importinfos[i].name)) ++ { ++ chat("Found %s in importlib list\n", name); ++ return &importlib->importinfos[i]; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int *helpcontext, const char **helpstring) ++{ ++ const attr_t *attr; ++ int flags; ++ ++ *invokekind = 1 /* INVOKE_FUNC */; ++ *helpcontext = -2; ++ *helpstring = NULL; ++ ++ if (!func->attrs) return 0; ++ ++ flags = 0; ++ ++ LIST_FOR_EACH_ENTRY(attr, func->attrs, const attr_t, entry) ++ { ++ expr_t *expr = attr->u.pval; ++ switch(attr->type) ++ { ++ case ATTR_BINDABLE: ++ flags |= 0x4; /* FUNCFLAG_FBINDABLE */ ++ break; ++ case ATTR_DEFAULTBIND: ++ flags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */ ++ break; ++ case ATTR_DEFAULTCOLLELEM: ++ flags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */ ++ break; ++ case ATTR_DISPLAYBIND: ++ flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */ ++ break; ++ case ATTR_HELPCONTEXT: ++ *helpcontext = expr->u.lval; ++ break; ++ case ATTR_HELPSTRING: ++ *helpstring = attr->u.pval; ++ break; ++ case ATTR_HIDDEN: ++ flags |= 0x40; /* FUNCFLAG_FHIDDEN */ ++ break; ++ case ATTR_ID: ++ *dispid = expr->cval; ++ break; ++ case ATTR_IMMEDIATEBIND: ++ flags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */ ++ break; ++ case ATTR_NONBROWSABLE: ++ flags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */ ++ break; ++ case ATTR_PROPGET: ++ *invokekind = 0x2; /* INVOKE_PROPERTYGET */ ++ break; ++ case ATTR_PROPPUT: ++ *invokekind = 0x4; /* INVOKE_PROPERTYPUT */ ++ break; ++ case ATTR_PROPPUTREF: ++ *invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */ ++ break; ++ /* FIXME: FUNCFLAG_FREPLACEABLE */ ++ case ATTR_REQUESTEDIT: ++ flags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */ ++ break; ++ case ATTR_RESTRICTED: ++ flags |= 0x1; /* FUNCFLAG_FRESTRICTED */ ++ break; ++ case ATTR_SOURCE: ++ flags |= 0x2; /* FUNCFLAG_FSOURCE */ ++ break; ++ case ATTR_UIDEFAULT: ++ flags |= 0x200; /* FUNCFLAG_FUIDEFAULT */ ++ break; ++ case ATTR_USESGETLASTERROR: ++ flags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return flags; ++} ++ ++static int get_param_flags(const var_t *param) ++{ ++ const attr_t *attr; ++ int flags, in, out; ++ ++ if (!param->attrs) return 0; ++ ++ flags = 0; ++ in = out = 0; ++ ++ LIST_FOR_EACH_ENTRY(attr, param->attrs, const attr_t, entry) ++ { ++ switch(attr->type) ++ { ++ case ATTR_IN: ++ in++; ++ break; ++ case ATTR_OUT: ++ out++; ++ break; ++ case ATTR_PARAMLCID: ++ flags |= 0x2000; ++ break; ++ case ATTR_RETVAL: ++ flags |= 0x80; ++ break; ++ default: ++ chat("unhandled param attr %d\n", attr->type); ++ break; ++ } ++ } ++ ++ if (out) ++ { ++ if (in) ++ flags |= 0x8000; ++ else ++ flags |= 0x4000; ++ } ++ else if (!in) ++ flags |= 0xc000; ++ ++ return flags; ++} ++ ++ ++static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, var_t *func, ++ int idx, int dispid, short base_offset, struct sltg_hrefmap *hrefmap) ++{ ++ struct sltg_data ret_data, *arg_data; ++ int arg_count = 0, arg_data_size, optional = 0, defaults = 0, old_size; ++ int funcflags = 0, invokekind = 1 /* INVOKE_FUNC */, helpcontext; ++ const char *helpstring; ++ const var_t *arg; ++ short ret_desc_offset, *arg_desc_offset, arg_offset; ++ struct sltg_function func_desc; ++ ++ chat("add_func_desc: %s, idx %#x, dispid %#x\n", func->name, idx, dispid); ++ ++ old_size = data->size; ++ ++ init_sltg_data(&ret_data); ++ ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->declspec.type), ++ 0, 0, base_offset, NULL, hrefmap); ++ dump_var_desc(ret_data.data, ret_data.size); ++ ++ arg_data_size = 0; ++ arg_offset = base_offset + sizeof(struct sltg_function); ++ ++ if (ret_data.size > sizeof(short)) ++ { ++ arg_data_size += ret_data.size; ++ arg_offset += ret_data.size; ++ } ++ ++ if (type_function_get_args(func->declspec.type)) ++ { ++ int i = 0; ++ ++ arg_count = list_count(type_function_get_args(func->declspec.type)); ++ ++ arg_data = xmalloc(arg_count * sizeof(*arg_data)); ++ arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset)); ++ ++ arg_offset += arg_count * 2 * sizeof(short); ++ ++ LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry) ++ { ++ const attr_t *attr; ++ short param_flags = get_param_flags(arg); ++ ++ chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n", ++ i, arg, arg->name, arg->declspec.type, arg->declspec.type->name); ++ ++ init_sltg_data(&arg_data[i]); ++ ++ ++ arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->declspec.type, param_flags, 0, ++ arg_offset, NULL, hrefmap); ++ dump_var_desc(arg_data[i].data, arg_data[i].size); ++ ++ if (arg_data[i].size > sizeof(short)) ++ { ++ arg_data_size += arg_data[i].size; ++ arg_offset += arg_data[i].size;; ++ } ++ ++ i++; ++ ++ if (!arg->attrs) continue; ++ ++ LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry) ++ { ++ if (attr->type == ATTR_DEFAULTVALUE) ++ defaults++; ++ else if(attr->type == ATTR_OPTIONAL) ++ optional++; ++ } ++ } ++ } ++ ++ funcflags = get_func_flags(func, &dispid, &invokekind, &helpcontext, &helpstring); ++ ++ if (base_offset != -1) ++ chat("add_func_desc: flags %#x, dispid %#x, invokekind %d, helpcontext %#x, helpstring %s\n", ++ funcflags, dispid, invokekind, helpcontext, helpstring); ++ ++ func_desc.magic = 0x6c; /* always write flags to simplify calculations */ ++ func_desc.flags = (invokekind << 4) | 0x02; ++ if (idx & 0x80000000) ++ { ++ func_desc.next = -1; ++ idx &= ~0x80000000; ++ } ++ else ++ func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short); ++ func_desc.name = base_offset != -1 ? add_name(typelib, func->name) : -1; ++ func_desc.dispid = dispid; ++ func_desc.helpcontext = helpcontext; ++ func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(typelib, helpstring) : -1; ++ func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1; ++ func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */; ++ func_desc.retnextopt = (optional << 1); ++ if (ret_data.size > sizeof(short)) ++ { ++ func_desc.rettype = base_offset + sizeof(func_desc) + ret_desc_offset; ++ if (arg_count) ++ func_desc.arg_off += ret_data.size; ++ } ++ else ++ { ++ func_desc.retnextopt |= 0x80; ++ func_desc.rettype = *(short *)ret_data.data; ++ } ++ func_desc.vtblpos = idx * pointer_size; ++ func_desc.funcflags = funcflags; ++ ++ append_data(data, &func_desc, sizeof(func_desc)); ++ ++ arg_offset = base_offset + sizeof(struct sltg_function); ++ ++ if (ret_data.size > sizeof(short)) ++ { ++ append_data(data, ret_data.data, ret_data.size); ++ func_desc.arg_off += ret_data.size; ++ arg_offset += ret_data.size; ++ } ++ ++ if (arg_count) ++ { ++ int i = 0; ++ ++ arg_offset += arg_count * 2 * sizeof(short); ++ ++ LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry) ++ { ++ short name, type_offset; ++ ++ name = base_offset != -1 ? add_name(typelib, arg->name) : -1; ++ ++ if (arg_data[i].size > sizeof(short)) ++ { ++ type_offset = (arg_offset + arg_desc_offset[i]); ++ arg_offset += arg_data[i].size; ++ } ++ else ++ { ++ name |= 1; ++ type_offset = *(short *)arg_data[i].data; ++ } ++ ++ append_data(data, &name, sizeof(name)); ++ append_data(data, &type_offset, sizeof(type_offset)); ++ ++ if (base_offset != -1) ++ chat("add_func_desc: arg[%d] - name %s (%#x), type_offset %#x\n", ++ i, arg->name, name, type_offset); ++ ++ i++; ++ } ++ ++ for (i = 0; i < arg_count; i++) ++ { ++ if (arg_data[i].size > sizeof(short)) ++ append_data(data, arg_data[i].data, arg_data[i].size); ++ } ++ } ++ ++ return data->size - old_size; ++} ++ ++static void write_impl_href(struct sltg_data *data, short href) ++{ ++ struct sltg_impl_info impl_info; ++ ++ impl_info.res00 = 0x004a; ++ impl_info.next = -1; ++ impl_info.res04 = -1; ++ impl_info.impltypeflags = 0; ++ impl_info.res07 = 0x80; ++ impl_info.res08 = 0x0012; ++ impl_info.ref = href; ++ impl_info.res0c = 0x4001; ++ impl_info.res0e = -2; /* 0xfffe */ ++ impl_info.res10 = -1; ++ impl_info.res12 = 0x001d; ++ impl_info.pos = 0; ++ ++ append_data(data, &impl_info, sizeof(impl_info)); ++} ++ ++static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface) ++{ ++ const statement_t *stmt_func; ++ importinfo_t *ref_importinfo = NULL; ++ short inherit_href = -1; ++ struct sltg_data data; ++ struct sltg_hrefmap hrefmap; ++ const char *index_name; ++ struct sltg_typeinfo_header ti; ++ struct sltg_member_header member; ++ struct sltg_tail tail; ++ int member_offset, base_offset, func_data_size, i; ++ int func_count, inherited_func_count = 0; ++ int dispid, inherit_level = 0; ++ ++ if (iface->typelib_idx != -1) return; ++ ++ chat("add_interface_typeinfo: type %p, type->name %s\n", iface, iface->name); ++ ++ if (!iface->details.iface) ++ { ++ error("interface %s is referenced but not defined\n", iface->name); ++ return; ++ } ++ ++ if (is_attr(iface->attrs, ATTR_DISPINTERFACE)) ++ { ++ error("support for dispinterface %s is not implemented\n", iface->name); ++ return; ++ } ++ ++ hrefmap.href_count = 0; ++ hrefmap.href = NULL; ++ ++ if (type_iface_get_inherit(iface)) ++ { ++ type_t *inherit; ++ ++ inherit = type_iface_get_inherit(iface); ++ ++ chat("add_interface_typeinfo: inheriting from base interface %s\n", inherit->name); ++ ++ ref_importinfo = find_importinfo(typelib->typelib, inherit->name); ++ ++ if (!ref_importinfo && type_iface_get_inherit(inherit)) ++ add_interface_typeinfo(typelib, inherit); ++ ++ if (ref_importinfo) ++ error("support for imported interfaces is not implemented\n"); ++ ++ inherit_href = local_href(&hrefmap, inherit->typelib_idx); ++ ++ while (inherit) ++ { ++ inherit_level++; ++ inherited_func_count += list_count(type_iface_get_stmts(inherit)); ++ inherit = type_iface_get_inherit(inherit); ++ } ++ } ++ ++ /* check typelib_idx again, it could have been added while resolving the parent interface */ ++ if (iface->typelib_idx != -1) return; ++ ++ iface->typelib_idx = typelib->n_file_blocks; ++ ++ /* pass 1: calculate function descriptions data size */ ++ init_sltg_data(&data); ++ ++ STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) ++ { ++ add_func_desc(typelib, &data, stmt_func->u.var, -1, -1, -1, &hrefmap); ++ } ++ ++ func_data_size = data.size; ++ ++ /* pass 2: write function descriptions */ ++ init_sltg_data(&data); ++ ++ func_count = list_count(type_iface_get_stmts(iface)); ++ ++ index_name = add_typeinfo_block(typelib, iface, TKIND_INTERFACE); ++ ++ init_typeinfo(&ti, iface, TKIND_INTERFACE, &hrefmap); ++ append_data(&data, &ti, sizeof(ti)); ++ ++ write_hrefmap(&data, &hrefmap); ++ ++ member_offset = data.size; ++ base_offset = 0; ++ ++ member.res00 = 0x0001; ++ member.res02 = 0xffff; ++ member.res04 = 0x01; ++ member.extra = func_data_size; ++ if (inherit_href != -1) ++ { ++ member.extra += sizeof(struct sltg_impl_info); ++ base_offset += sizeof(struct sltg_impl_info); ++ } ++ append_data(&data, &member, sizeof(member)); ++ ++ if (inherit_href != -1) ++ write_impl_href(&data, inherit_href); ++ ++ i = 0; ++ dispid = 0x60000000 | (inherit_level << 16); ++ ++ STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) ++ { ++ int idx = inherited_func_count + i; ++ ++ if (i == func_count - 1) idx |= 0x80000000; ++ ++ base_offset += add_func_desc(typelib, &data, stmt_func->u.var, ++ idx, dispid + i, base_offset, &hrefmap); ++ i++; ++ } ++ ++ init_sltg_tail(&tail); ++ ++ tail.cFuncs = func_count; ++ tail.funcs_off = 0; ++ tail.funcs_bytes = func_data_size; ++ tail.cbSizeInstance = pointer_size; ++ tail.cbAlignment = pointer_size; ++ tail.cbSizeVft = (inherited_func_count + func_count) * pointer_size; ++ tail.type_bytes = data.size - member_offset - sizeof(member); ++ tail.res24 = 0; ++ tail.res26 = 0; ++ if (inherit_href != -1) ++ { ++ tail.cImplTypes++; ++ tail.impls_off = 0; ++ tail.impls_bytes = 0; ++ ++ tail.funcs_off += sizeof(struct sltg_impl_info); ++ } ++ append_data(&data, &tail, sizeof(tail)); ++ ++ add_block(typelib, data.data, data.size, index_name); ++} ++ ++static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type) ++{ ++ error("add_enum_typeinfo: %s not implemented\n", type->name); ++} ++ ++static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type) ++{ ++ error("add_union_typeinfo: %s not implemented\n", type->name); ++} ++ ++static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type) ++{ ++ error("add_coclass_typeinfo: %s not implemented\n", type->name); ++} ++ ++static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type) ++{ ++ chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type)); ++ ++ switch (type_get_type(type)) ++ { ++ case TYPE_INTERFACE: ++ add_interface_typeinfo(typelib, type); ++ break; ++ case TYPE_STRUCT: ++ add_structure_typeinfo(typelib, type); ++ break; ++ case TYPE_ENUM: ++ add_enum_typeinfo(typelib, type); ++ break; ++ case TYPE_UNION: ++ add_union_typeinfo(typelib, type); ++ break; ++ case TYPE_COCLASS: ++ add_coclass_typeinfo(typelib, type); ++ break; ++ case TYPE_BASIC: ++ case TYPE_POINTER: ++ break; ++ default: ++ error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name); ++ break; ++ } ++} ++ ++static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt) ++{ ++ switch(stmt->type) ++ { ++ case STMT_LIBRARY: ++ case STMT_IMPORT: ++ case STMT_PRAGMA: ++ case STMT_CPPQUOTE: ++ case STMT_DECLARATION: ++ /* not included in typelib */ ++ break; ++ case STMT_IMPORTLIB: ++ /* not processed here */ ++ break; ++ ++ case STMT_TYPEDEF: ++ { ++ const type_list_t *type_entry = stmt->u.type_list; ++ for (; type_entry; type_entry = type_entry->next) ++ { ++ /* in old style typelibs all types are public */ ++ add_type_typeinfo(typelib, type_entry->type); ++ } ++ break; ++ } ++ ++ case STMT_MODULE: ++ add_module_typeinfo(typelib, stmt->u.type); ++ break; ++ ++ case STMT_TYPE: ++ case STMT_TYPEREF: ++ { ++ type_t *type = stmt->u.type; ++ add_type_typeinfo(typelib, type); ++ break; ++ } ++ ++ default: ++ error("add_statement: unhandled statement type %d\n", stmt->type); ++ break; ++ } ++} ++ ++static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start) ++{ ++ char pad[0x40]; ++ struct sltg_header ++ { ++ int magic; ++ short n_file_blocks; ++ short res06; ++ short size_of_index; ++ short first_blk; ++ GUID uuid; ++ int res1c; ++ int res20; ++ } header; ++ struct sltg_block_entry ++ { ++ int length; ++ short index_string; ++ short next; ++ } entry; ++ struct sltg_block *block; ++ int i; ++ ++ header.magic = 0x47544c53; ++ header.n_file_blocks = sltg->n_file_blocks + 1; ++ header.res06 = 9; ++ header.size_of_index = sltg->index.size; ++ header.first_blk = 1; ++ header.uuid = sltg_library_guid; ++ header.res1c = 0x00000044; ++ header.res20 = 0xffff0000; ++ ++ put_data(&header, sizeof(header)); ++ ++ block = sltg->blocks; ++ for (i = 0; i < sltg->n_file_blocks - 1; i++) ++ { ++ assert(block->next != NULL); ++ ++ entry.length = block->length; ++ entry.index_string = block->index_string; ++ entry.next = header.first_blk + i + 1; ++ chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n", ++ i, entry.length, entry.index_string, entry.next); ++ put_data(&entry, sizeof(entry)); ++ ++ block = block->next; ++ } ++ ++ assert(block->next == NULL); ++ ++ /* library block length includes helpstrings and name table */ ++ entry.length = block->length + 0x40 + 2 + sltg->typeinfo_size + 4 + 6 + 12 + 0x200 + sltg->name_table.size + 12; ++ entry.index_string = block->index_string; ++ entry.next = 0; ++ chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n", ++ i, entry.length, entry.index_string, entry.next); ++ put_data(&entry, sizeof(entry)); ++ ++ chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size); ++ put_data(sltg->index.data, sltg->index.size); ++ memset(pad, 0, 9); ++ put_data(pad, 9); ++ ++ block = sltg->blocks; ++ for (i = 0; i < sltg->n_file_blocks - 1; i++) ++ { ++ chat("sltg_write_header: writing block %d: %d bytes\n", i, block->length); ++ ++ put_data(block->data, block->length); ++ block = block->next; ++ } ++ ++ assert(block->next == NULL); ++ ++ /* library block */ ++ chat("library_block_start = %#lx\n", (SIZE_T)output_buffer_pos); ++ *library_block_start = output_buffer_pos; ++ chat("sltg_write_header: writing library block %d: %d bytes\n", i, block->length); ++ put_data(block->data, block->length); ++ ++ chat("sltg_write_header: writing pad 0x40 bytes\n"); ++ memset(pad, 0xff, 0x40); ++ put_data(pad, 0x40); ++} ++ ++static void sltg_write_typeinfo(struct sltg_typelib *typelib) ++{ ++ int i; ++ struct sltg_block *block; ++ short count = typelib->typeinfo_count; ++ ++ put_data(&count, sizeof(count)); ++ ++ block = typelib->typeinfo; ++ for (i = 0; i < typelib->typeinfo_count; i++) ++ { ++ chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, block->length); ++ ++ put_data(block->data, block->length); ++ block = block->next; ++ } ++ assert(block == NULL); ++} ++ ++static void sltg_write_helpstrings(struct sltg_typelib *typelib) ++{ ++ static const char dummy[6]; ++ ++ chat("sltg_write_helpstrings: writing dummy 6 bytes\n"); ++ ++ put_data(dummy, sizeof(dummy)); ++} ++ ++static void sltg_write_nametable(struct sltg_typelib *typelib) ++{ ++ static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff }; ++ char pad[0x200]; ++ ++ chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size); ++ ++ put_data(dummy, sizeof(dummy)); ++ memset(pad, 0xff, 0x200); ++ put_data(pad, 0x200); ++ put_data(&typelib->name_table.size, sizeof(typelib->name_table.size)); ++ put_data(typelib->name_table.data, typelib->name_table.size); ++} ++ ++static void sltg_write_remainder(void) ++{ ++ static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff }; ++ static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 }; ++ static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 }; ++ static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 }; ++ int pad; ++ ++ pad = 0x01ffff01; ++ put_data(&pad, sizeof(pad)); ++ pad = 0; ++ put_data(&pad, sizeof(pad)); ++ ++ put_data(dummy1, sizeof(dummy1)); ++ ++ put_data(&sltg_library_guid, sizeof(sltg_library_guid)); ++ ++ put_data(TYPELIB, sizeof(TYPELIB)); ++ ++ put_data(dummy2, sizeof(dummy2)); ++ put_data(dummy3, sizeof(dummy3)); ++} ++ ++static void save_all_changes(struct sltg_typelib *typelib) ++{ ++ int library_block_start; ++ int *name_table_offset; ++ ++ sltg_write_header(typelib, &library_block_start); ++ sltg_write_typeinfo(typelib); ++ ++ name_table_offset = (int *)(output_buffer + output_buffer_pos); ++ chat("name_table_offset = %#lx\n", (SIZE_T)output_buffer_pos); ++ put_data(&library_block_start, sizeof(library_block_start)); ++ ++ sltg_write_helpstrings(typelib); ++ ++ *name_table_offset = output_buffer_pos - library_block_start; ++ chat("*name_table_offset = %#x\n", *name_table_offset); ++ ++ sltg_write_nametable(typelib); ++ sltg_write_remainder(); ++ ++ if (strendswith(typelib_name, ".res")) /* create a binary resource file */ ++ { ++ char typelib_id[13] = "#1"; ++ ++ expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID); ++ if (expr) ++ sprintf(typelib_id, "#%d", expr->cval); ++ add_output_to_resources("TYPELIB", typelib_id); ++ output_typelib_regscript(typelib->typelib); ++ } ++ else flush_output_buffer(typelib_name); ++} ++ ++int create_sltg_typelib(typelib_t *typelib) ++{ ++ struct sltg_typelib sltg; ++ const statement_t *stmt; ++ void *library_block; ++ int library_block_size, library_block_index; ++ ++ sltg.typelib = typelib; ++ sltg.typeinfo_count = 0; ++ sltg.typeinfo_size = 0; ++ sltg.typeinfo = NULL; ++ sltg.blocks = NULL; ++ sltg.n_file_blocks = 0; ++ sltg.first_block = 1; ++ ++ init_index(&sltg.index); ++ init_name_table(&sltg); ++ init_library(&sltg); ++ ++ library_block = create_library_block(&sltg, &library_block_size, &library_block_index); ++ ++ if (typelib->stmts) ++ LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry) ++ add_statement(&sltg, stmt); ++ ++ add_block_index(&sltg, library_block, library_block_size, library_block_index); ++ ++ save_all_changes(&sltg); ++ ++ return 1; ++} From 1dd591ba935d2b3841dadb06d35113cac5a4c536 Mon Sep 17 00:00:00 2001 From: belliash Date: Fri, 14 Aug 2020 14:05:31 +0200 Subject: [PATCH 05/32] Import windres-compatible wrapper for LLVM. --- tools/windres.c | 558 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/xtchain.h | 162 ++++++++++++++ 2 files changed, 720 insertions(+) create mode 100644 tools/windres.c create mode 100644 tools/xtchain.h diff --git a/tools/windres.c b/tools/windres.c new file mode 100644 index 0000000..5171ad3 --- /dev/null +++ b/tools/windres.c @@ -0,0 +1,558 @@ +/** + * PROJECT: XTchain + * LICENSE: See COPYING.md in the top level directory + * FILE: tools/windres.c + * DESCRIPTION: WINDRES compatible interface to LLVM + * DEVELOPERS: Josh de Kock + * Martin Storsjo + * Rafal Kupiec + */ + +#include "xtchain.h" + +#define WINDRES_VERSION "1.0" + +#ifndef DEFAULT_TARGET +#define DEFAULT_TARGET "x86_64-w64-mingw32" +#endif + +#include + +#define _tspawnvp_escape _spawnvp + +#include +#include + +#define _P_WAIT 0 + +static +int +_spawnvp(int mode, + const char *filename, + const char * const *argv) +{ + pid_t pid; + + if(!(pid = fork())) + { + execvp(filename, (char **) argv); + perror(filename); + exit(1); + } + + int stat = 0; + + if(waitpid(pid, &stat, 0) == -1) + { + return -1; + } + + if(WIFEXITED(stat)) + { + return WEXITSTATUS(stat); + } + errno = EIO; + + return -1; +} + +static +const +char *unescape_cpp(const char *str) +{ + char *out = strdup(str); + int len = strlen(str); + int i, outpos = 0; + + for(i = 0; i < len - 1; i++) + { + if(str[i] == '\\' && str[i + 1] == '"') + { + continue; + } + out[outpos++] = str[i]; + } + + while(i < len) + { + out[outpos++] = str[i++]; + } + + out[outpos++] = '\0'; + + return out; +} + +static +void print_version(void) +{ + printf("XTchain windres (GNU windres compatible) %s\n", WINDRES_VERSION); + exit(-1); +} + +static +void print_help(void) +{ + printf( + "usage: llvm-windres